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


    有 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 }
  • 相关阅读:
    正则表达式的与或非
    正则中需要转义的符号
    HTTP 错误状态码讯息
    HTTP协议详解
    TCP/IP、Http、Socket的区别
    CSS样式中标点符号的作用
    HighCharts: 设置时间图x轴的宽度
    可以尝试用Google Font API来摆脱网页字体的单调 仅仅抛砖引玉
    Oracle 权限(grant、revoke)
    网站加上图标
  • 原文地址:https://www.cnblogs.com/xiehuazhen/p/12557699.html
Copyright © 2020-2023  润新知