背包九讲之八:背包问题求方案数

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出 最优选法的方案数。注意答案可能很大,请输出答案模 10⁹+7 的结果。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一个整数,表示方案数 模 10⁹+7 的结果。
数据范围
0<N,V≤1000
0<vi,wi≤1000
输入样例
4 5
1 2
2 4
3 4
4 6
输出样例
2
法一:根据体积恰好为j时价值的大小来更新方案数
 1 #include<iostream>
 2 #include<climits>
 3 #include<algorithm>
 4 using namespace std;
 5 const int n = 1001;
 6 int N, V, v, w, f[n], g[n];//f[j]、g[j]分别表示体积恰好为j时的最大价值、方案数
 7 int mod = 1000000007;
 8 int main() {
 9        cin >> N >> V;
10        g[0] = 1;
11        for (int i = 1; i <= V; ++i)
12               f[i] = INT_MIN; //除0以外,全部设为负无穷,确保都是从f[0]传递过去的
13        for (int i = 0; i < N; ++i) {
14               cin >> v >> w;
15               for (int j = V; j >= v; --j) {
16                      int s = 0, t = max(f[j], f[j - v] + w);
17                      if (t == f[j])
18                            s += g[j]; //添加不更新的方案
19                      if (t == f[j - v] + w)
20                            s += g[j - v]; //添加更新的方案
21                      if (s >= mod)
22                            s -= mod;
23                      f[j] = t;
24                      g[j] = s;
25               }
26        }
27        int maxn = 0, res = 0;
28        for (int i = 0; i <= V; ++i)
29               maxn = max(maxn, f[i]); //获取最大价值
30        for (int i = 0; i <= V; ++i)
31               if (maxn == f[i]) {     //等于最大价值的方案都添加
32                      res += g[i];
33                      if (res >= mod)
34                            res -= mod;
35               }
36        cout << res;
37 }
法二:根据体积最大为j时价值的大小来更新方案数
 1 #include<iostream>
 2 #include<climits>
 3 #include<algorithm>
 4 using namespace std;
 5 const int n = 1001;
 6 int N, V, v, w, f[n], g[n];//f[j]、g[j]分别表示体积最大为j时的最大价值、方案数
 7 int mod = 1000000007;
 8 int main() {
 9        for (int i = 0; i < n; ++i)
10               g[i] = 1; //默认体积最大为i时方案数为1
11        cin >> N >> V;
12        for (int i = 0; i < N; ++i) {
13               cin >> v >> w;
14               for (int j = V; j >= v; --j) {
15                      if (f[j] < f[j - v] + w) {
16                            f[j] = f[j - v] + w;
17                            g[j] = g[j - v]; //使用新方案时更新方案数为g[j-v]的方案数
18                      }
19                      else if (f[j] == f[j - v] + w)
20                            g[j] = (g[j] + g[j - v]) % mod; //原方案数加跟新方案数
21                      //使用原方案时方案数不变,故不作操作。
22               }
23        }
24        cout << g[V];
25 }
原文地址:https://www.cnblogs.com/xiehuazhen/p/12557699.html