HDU2602 Bone Collector 动态规划 DP 入门 0-1背包
状态转移公式:
dp[i][j] = max(dp[i-1][j] , dp[i-1][j - vol[i]] + val[i])
在体积为j 时放入第i 件物品的最大价值, 其中val[i] 表示物品i 的价值, vol[i] 表示i 所占空间。
8020430 | 2013-04-07 12:54:12 | Accepted | 2602 | 125MS | 4220K | 1510 B | C++ | 罗维 |
二维数组
1 /* 2 hdu2602 3 dp[i][j] 表示放入第i项物品体积为j的最大价值 4 思路: 5 将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略 6 (放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题 7 就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转 8 化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再 9 加上通过放入第i件物品获得的价值w[i]。(背包九讲) 10 若vol[i] > j 11 那么就不放i,直接dp[i][j] = dp[i-1][j] 12 若vol[i] <= j 13 状态转移方程: 14 dp[i][j] = max(dp[i-1][j] , dp[i-1][j-vol[i]+val[i]) 15 dp[i-1][j]表示不放i件物品 16 dp[i-1][j-vol[i]]+val[i]表示放入第i件物品 17 j-vol[i] -> 总体积为j, 若放入i那么体积为j+vol[i],可是总体积大小只有j,所以要放入vol[i],就必须拿出vol[i]大小的体积出来好放入i. 18 因此求出dp[i-1][j-vol[i]]时的价值再加上val[i]的价值就是放入i,总体积为j的价值。 19 20 */ 21 22 #include <iostream> 23 #include <algorithm> 24 25 using namespace std; 26 27 int dp[1001][1001],vol[1001],val[1001]; 28 29 int main() 30 { 31 int t,n,i,j,v; 32 cin>>t; 33 while(t--) 34 { 35 cin>>n>>v; 36 for(i=1;i<=n;i++) 37 scanf("%d",&val[i]); 38 for(i=1;i<=n;i++) 39 scanf("%d",&vol[i]); 40 memset(dp,0,sizeof(dp)); //初始化 41 for (i=0; i<=v; i++) 42 for (j=1; j<=n; j++) 43 if (vol[j]<=i && dp[j-1][i] < dp[j-1][i-vol[j]] + val[j]) 44 dp[j][i] = dp[j-1][i-vol[j]] + val[j]; 45 else 46 dp[j][i] = dp[j-1][i]; 47 cout<<dp[n][v]<<endl; 48 } 49 return 0; 50 }
8020699 | 2013-04-07 13:32:25 | Accepted | 2602 | 31MS | 308K | 1460 B | C++ | 罗维 |
一维数组
#include <iostream> #include <algorithm> using namespace std; int dp[1001],vol[1001],val[1001]; int maxx(int a, int b) { return a > b ? a : b; } int main() { int t,n,i,j,v; cin>>t; while(t--) { cin>>n>>v; for(i=1;i<=n;i++) scanf("%d",&val[i]); for(i=1;i<=n;i++) scanf("%d",&vol[i]); memset(dp,0,sizeof(dp)); //初始化 for (j=1; j<=n; j++) for (i=v; i>=vol[j]; i--) dp[i] = maxx(dp[i], dp[i-vol[j]]+val[j]); cout<<dp[v]<<endl; } return 0; }
2013年4月7日13:01:22