天天看點

hdu 3339 In Action(最短路+01背包)

題目:

        連結點選打開連結

題意:

        有N個發電站和M條路,給出每兩條路之間的耗油量,then,N行代表發電站的能量。求最小耗油量,隻有控制超過總能量的一半,才能成功,否則impossible。

思路:

        求最少的耗油量,明顯是最短路問題,然後,要求控制的電量要超過一半用01背包解決:V是總電量一半+1,dijkstra求得的dis[]是價值,每個發電站的電量v[]是花費。

代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 100000000
using namespace std;

int n,m;
int map[110][110],dis[110];
int dp[10010],v[110];
int result;

void dijkstra()
{
    int vis[110];
    memset(vis,0,sizeof(vis));
    for(int i=1; i<=n; i++)
    {
        dis[i] = map[0][i];
    }
    dis[0] = 0;
    for(int i=1; i<n; i++)
    {
        int x,minn = INF;
        for(int y=1; y<=n; y++)
        {
            if(!vis[y] && minn > dis[y])
                minn = dis[x=y];
        }
        vis[x] = 1;
        for(int y=1; y<=n; y++)
        {
            if(dis[y] > dis[x] + map[x][y])
                dis[y] = dis[x] + map[x][y];
        }
    }
}

int main()
{
    //freopen("input.txt","r",stdin);
    int t;
    int st,ed,di;
    cin>>t;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<=n; i++)
        {
            for(int j=0; j<=n; j++)
                map[i][j] = INF;
        }
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&st,&ed,&di);
            if(map[st][ed] > di)
                map[st][ed] = map[ed][st] = di;
        }
        int sum = 0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&v[i]);
            sum += v[i];
        }
        dijkstra();//最短路求從0到每個發電站的耗油量,即dis[],01背包中的價值
        for(int i=1; i<=sum; i++)
        {
            dp[i] = INF;
        }
        dp[0] = 0;
        for(int i=1; i<=n; i++)//01背包求最小
        {
            for(int j=sum; j>=v[i]; j--)
                dp[j] = min(dp[j],dp[j-v[i]] + dis[i]);
        }
        int V = sum/2 + 1;//背包容量為大于總電量和的一半
        int result = INF;
        for(int i=V; i<=sum; i++)
        {
            if(dp[i] < result)
                result = dp[i];
        }
        if(result == INF)
            printf("impossible\n");
        else
            printf("%d\n",result);
    }
    return 0;
}
           

-------------------------------------------------------------------------------------------

戰鬥,從不停歇;奮鬥,永不停歇~~~~~~~~~~~~~~~~~~~~~~~