HDU3339 最短路加01背包


题意大意就是说:有n个电站,每个电站都有一定的电量,电站之间有一定的距离,我们要从0点出发去占据一些电站,使得占据的电站电量之和不小于总电量的一半,求达到要求所要走的最短距离。若是可能的话,输出间隔,不然输出不成能。我们知道电站都是连通的,只要0点与任何一个电站连通,我们就可以占据所有电站,若是0点不与任何一个电站相连,就是不成能实现,也就是说0点到任何一个电站的间隔都是无穷。

 

我们从0点开端派出一些坦克去占据一些电站,坦克到每个电站都有必然间隔,而占据每个电站之后可以获得必然电量,间隔就相当于体积,电量就相当于价值,这不是就01背包吗?01背包凡是的问法是给定体积,求获得最大的价值,这里的问法是给订价值,求正好获得或多于该价值时的最小体积。我们只要畴前向后搜刮,找到第一个大于该价值的体积即可。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#define INF 999999999
#define M 105
using namespace std;

int main()
{
    int map[M][M],p[M],dp[M*M];
    int n,m,t,i,j,k,sum,ave;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=0;i<=n;i++)
        {
            for(j=0;j<=n;j++)
            {
                map[i][j]=INF;
            }
        }
        while(m--)
        {
            int u,v,d;
            scanf("%d%d%d",&u,&v,&d);
            map[u][v]=map[v][u]=min(map[u][v],d);
        }
        sum=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&p[i]);
            sum+=p[i];
        }
        ave=sum/2;
        for(k=0;k<=n;k++)
        {
            for(i=0;i<=n;i++)
            {
                for(j=0;j<=n;j++)
                {
                    map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
                }
            }
        }
        int temp=0;
        for(i=1;i<=n;i++)
        {
            if(map[0][i]<INF-10)
                temp+=map[0][i];
        }
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
            for(j=temp;j>=map[0][i];j--)
            {
                dp[j]=max(dp[j],dp[j-map[0][i]]+p[i]);
            }
        }
        int flag=0;
        for(i=0;i<=temp;i++)
        {
            if(dp[i]>ave)
            {
                printf("%d\n",i);
                flag=1;
                break;
            }
        }
        if(flag==0)
            printf("impossible\n");
    }
    return 0;
}


你可能感兴趣的:(HDU3339 最短路加01背包)