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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3339

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

 

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

 

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int INF=1234567;
  6 const int MAX=105;
  7 int map[MAX][MAX];
  8 int disit[MAX];
  9 int visit[MAX];
 10 int value[MAX];
 11 int DP[MAX*MAX];
 12 int n,m,tot;
 13 void init()
 14 {
 15     int i,j;
 16     memset(visit,0,sizeof(visit));
 17     memset(DP,0,sizeof(DP));
 18     for (i=0;i<=n;i++)
 19     {
 20         for(j=0;j<=n;j++)
 21             map[i][j]=INF;
 22         disit[i]=INF;
 23         map[i][i]=0;
 24     }
 25     tot=0;
 26 }
 27 void Dijstra()
 28 {
 29     int i,j,v,ma;
 30     for (i=0;i<=n;i++)
 31     {
 32         disit[i]=map[0][i];
 33     }
 34     disit[0]=0;
 35     visit[0]=1;
 36     for (i=1;i<=n;i++)
 37     {
 38         ma=INF;
 39         for (j=1;j<=n;j++)
 40             if(!visit[j]&&disit[j]<ma){
 41                 ma=disit[j];
 42                 v=j;
 43             }
 44             if(ma==INF)break;
 45             visit[v]=1;
 46             for (j=1;j<=n;j++)
 47                 if(!visit[j]&&disit[j]>disit[v]+map[v][j]){
 48                     disit[j]=disit[v]+map[v][j];
 49                 }
 50     }
 51 }
 52 int max(int x,int y)
 53 {
 54     if(x>y)return x;
 55     else return y;
 56 }
 57 int main()
 58 {
 59     int i,j,k,x,y,z,v,flag;
 60     scanf("%d",&k);
 61     while (k--)
 62     {
 63         scanf("%d%d",&n,&m);
 64         init();
 65         for (i=1;i<=m;i++)
 66         {
 67             scanf("%d%d%d",&x,&y,&z);
 68             if(map[x][y]>z)
 69                 map[x][y]=map[y][x]=z;
 70         }
 71         for (i=1;i<=n;i++)
 72         {
 73             scanf("%d",&value[i]);
 74             tot+=value[i];
 75         }
 76         Dijstra();
 77         flag=1;
 78         v=0;
 79         for (i=1;i<=n;i++)
 80         {
 81             v+=disit[i];
 82             if(disit[i]>=INF)
 83             {
 84                 flag=0;
 85                 break;
 86             }
 87         }
 88         if(!flag){printf("impossible\n");continue;}
 89         for (i=1;i<=n;i++)
 90             for (j=v;j>=disit[i];j--)
 91             {
 92                 DP[j]=max(DP[j],DP[j-disit[i]]+value[i]);
 93             }
 94             tot=(tot/2+1);
 95             for (i=1;i<=v;i++)
 96             {
 97                 if(DP[i]>=tot){
 98                     printf("%d\n",i);
 99                     break;
100                 }
101             }
102     }
103     return 0;    
104 }
posted @ 2012-04-17 15:06  我们一直在努力  阅读(284)  评论(0编辑  收藏  举报