完全背包问题
问题描述
有n种重量和价值分贝为wi, vi的物品。 从这些物品中挑选总重量不超过W的物品, 求挑选物品总价值的最大值。在这里, 每种物品可以挑选任意多件。
限制条件
1 <= n <= 100
1 <= wi, vi <= 100
1 <= W <= 10000
方案一:再用一个循环来遍历所有的取法
for (int i = 0; i < n; i++) { for (int j = 0; j <= W; j++) { for (int k = 0; k*bag[i].w <= j; k++) { dp[i+1][j] = max(dp[i+1][j], dp[i][j-k*bag[i].w]+k*bag[i].v); } } }
//事实上 列表可以发现重复的计算
//发现 dp[i][j-k*bag[i].w]+bag[i].v选择 k的情况 和 dp[i+1][j-bag[i].w]+bag[i].v中选择 k-1个情况是相同的计算
//所以 dp[i][j]中 k>= 1的计算已经在dp[i+1][j-bag[i].w]+bag[i].v完成
所以状态转移方程
dp[i][j] = max(dp[i][j], dp[i+1][j-w[i]]+v[i]);
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 5 using namespace std; 6 7 struct Bag 8 { 9 int w, v; 10 }bag[128]; 11 int main() 12 { 13 freopen("in.txt", "r", stdin); 14 int n,W; 15 while (~scanf("%d", &n)) 16 { 17 for (int i = 0; i < n; i++) 18 { 19 scanf("%d%d", &bag[i].w, &bag[i].v); 20 } 21 scanf("%d",&W); 23 int dp[128][128]; 24 memset(dp, 0, sizeof(dp));39 for (int i =0; i < n; i++) 40 { 41 for (int j = 0; j <= W; j++) 42 { 43 if (j < bag[i].w) dp[i+1][j] = dp[i][j]; 44 else dp[i+1][j] = max(dp[i][j], dp[i+1][j-bag[i].w]+bag[i].v);//dp[i][j]解决了k = 0的情况 dp[i+1][j-bag[i].w] 代替了 dp[i][j-bag[i].w]中 k>=1的情况 45 } 46 } 47 printf("%d\n", dp[n][W]); 48 } 49 return 0; 50 }