hdu 3339 In Action 最短路+(01)背包
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3339
题意大意就是说:有n个电站,每个电站都有一定的电量,电站之间有一定的距离,我们要从0点出发去占据一些电站,使得占据的电站电量之和不小于总电量的一半,求达到要求所要走的最短距离。若是可能的话,输出间隔,不然输出不成能。我们知道电站都是连通的,只要0点与任何一个电站连通,我们就可以占据所有电站,若是0点不与任何一个电站相连,就是不成能实现,也就是说0点到任何一个电站的间隔都是无穷。
我们从0点开端派出一些坦克去占据一些电站,坦克到每个电站都有必然间隔,而占据每个电站之后可以获得必然电量,间隔就相当于体积,电量就相当于价值,这不是就01背包吗?01背包凡是的问法是给定体积,求获得最大的价值,这里的问法是给订价值,求正好获得或多于该价值时的最小体积。我们只要畴前向后搜刮,找到第一个大于该价值的体积即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }