HDU3339:In Action(Dijkstra+01背包)

 题意: 有 n个发电站 编号 1到n  ,每个发电站有一个pow 值,  m条边 每条边有一个cost 值, 要求  选出一些点,使得这些点的pow值>sum(pow)/2 并且 从0号到每个点的最短距离和最小。 最短路+01背包,   0号到每个点的最短距离作为价值 , pow作为花费。

 
 
#include<bits/stdc++.h>
using namespace std;
struct node
{
    int to ,val;
};
const int mx = 105;
int dis[mx];
int dp[2000010];
int powv[101];
const int inf = 1e9;
int mp[101][101];
int n;
void floyd()
{
    for(int  k =0; k<=n; k++)
    {
        for(int i =0; i<=n; i++)
        {
            for(int j=0; j<=n; j++)
            {
                mp[i][j] = min(mp[i][j], mp[i][k]+mp[k][j]);
            }
        }
    }

}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        //memset(dp,0x3f3f3f3f,sizeof(dp));
        for(int i =1 ;i<=2000000;i++)
             dp[i] = inf;
        int   m;
        scanf("%d%d",&n,&m);
        for(int i =0; i<=n; i++)
        {

            for(int j =0; j<=n; j++)
            {
                mp[i][j] = inf;
            }  mp[i][i]=0;
        }
        int x,y,z;
        for(int i = 1; i<=m; i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            if(mp[x][y]>z)
            {
                mp[x][y] = mp[y][x] = z;
            }
        }
        floyd();
        int sum = 0;
        for(int i = 1; i<=n; i++)
        {
            scanf("%d",&powv[i]);
            sum+=powv[i];
        }
        for(int i = 1; i<=n; i++)
        {
            dis[i] =  mp[0][i];
        }
        dp[0]=0;
        for(int i = 1; i<=n; i++)
        {
            for(int j=sum; j>=powv[i]; j--)
            {
                dp[j] = min(dp[j],dp[j- powv[i]]+ dis[i]);
            }
        }
        int ans = 1e9;
        int g ;
        g= sum/2+1;
        for(int i  = sum; i>=g; i--)
        {
            ans =min(ans,dp[i]);
        }
        if(ans!=inf)
        {
            cout<<ans<<endl;
        }
        else
        {
            printf("impossible\n");
        }
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/theflowerofac/article/details/53084060