NYOJ 203
View Code
1 /* 2 最短路 + 0-1背包 3 先用 DIJ 求出 起点到各个点的最短距离 相当于 4 各个物品的体积,各个点的宝物数 相当于 价值 5 总粮食相当于 背包容量 6 剩下的就是 纯粹的 0-1背包问题了 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 #include<algorithm> 12 using namespace std; 13 14 const int size = 110; 15 const int inf = 999999999; 16 17 int v[size]; 18 int f[1000005]; 19 int w[size]; 20 int path[size][size]; 21 bool flag[size]; 22 int c,n,M; 23 24 void init() 25 { 26 int i,j; 27 for(i=0;i<=n;++i) 28 { 29 flag[i]=false; 30 path[i][i]=0; 31 w[i]=inf; 32 for(j=i+1;j<=n;++j) 33 path[i][j]=path[j][i]=inf; 34 } 35 } 36 37 void dij() 38 { 39 int i,j; 40 w[0]=0; 41 42 for(i=0;i<=n;++i) 43 { 44 int mi=inf; 45 int k=0; 46 for(j=0;j<=n;++j) 47 if(!flag[j]&&w[j]<mi) 48 { 49 mi=w[j]; 50 k=j; 51 } 52 flag[k]=true; 53 for(j=0;j<=n;++j) 54 { 55 if(!flag[j] && w[j]>mi+path[k][j]&& path[k][j]!=inf) 56 { 57 w[j]=mi+path[k][j]; 58 } 59 } 60 } 61 } 62 63 /*void Knapsack() 64 { 65 int jMax=min(w[n]-1,c); 66 for(int j=0;j<=jMax;++j) 67 m[n][j]=0; 68 for(int j=w[n];j<=c;++j) 69 m[n][j]=v[n]; 70 for(int i=n-1;i>1;--i) 71 { 72 jMax=min(w[i]-1,c); 73 for(int j=0;j<=jMax;j++) 74 m[i][j]=m[i+1][j]; 75 for(int j=w[i];j<=c;++j) 76 m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]); 77 } 78 m[1][c]=m[2][c]; 79 if(c>=w[1])m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]); 80 printf("%d\n",m[1][c]); 81 } 82 */ 83 84 void Knapsack() 85 { 86 int i,j; 87 for(i=1;i<=n;++i) 88 for(j=c;j>=w[i];--j) 89 if(f[j]<f[j-w[i]]+v[i]) 90 f[j]=f[j-w[i]]+v[i]; 91 } 92 int main() 93 { 94 int T,i,j,x,y,z,num,sum; 95 96 scanf("%d",&T); 97 while(T--) 98 { 99 scanf("%d%d%d",&c,&n,&M); 100 init(); 101 for(i=0;i<M;++i) 102 { 103 scanf("%d%d%d",&x,&y,&z); 104 if(path[x][y]>z) 105 path[x][y]=path[y][x]=z; 106 } 107 dij(); 108 for(i=1;i<=n;++i) 109 scanf("%d",&v[i]); 110 for(i=0;i<=c;++i) 111 f[i]=0; 112 Knapsack(); 113 printf("%d\n",f[c]); 114 } 115 return 0; 116 }