完全背包问题

问题描述

有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
", dp[n][W]);
48     }
49     return 0;
50 }
原文地址:https://www.cnblogs.com/oscar-cnblogs/p/6376456.html