题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=860

【志银】NYOJ《题目860》又见01背包

方法一:不用滚动数组(方法二为用滚动数组,为方法一的简化)

动态规划分析:最少要拿总价值一定,求所拿的最小质量(根据"最大能拿总重量一定,求能拿的最大价值"原理推导)

(PS:为了更好的理解,先不用滚动数组,直接开了两个数组,第一个数组用来储存最少要拿总价值为j时所拿的最小质量,第二个数组用来储存第一个的改变前状态)
例:
最大总质量sw = 5,物品数量n = 4;
          1   2  3  4 <-第i个物品
w[] = {2, 1, 3, 2} //重量
v[] = {3, 2, 4, 2} //价值
最大总质量sw = 5,最大总价值sv = 11,物品数量n = 4;

分析打表结果如下:

【志银】NYOJ《题目860》又见01背包

 1 #include<iostream>
 2 using namespace std;
 3 int main() {
 4   int n, sw, sv, v[105], w[105], m[10005], b[10005];  //n为物品数量,sw为总重量,sv为总价值
 5   while(cin >> n >> sw) {      //m[j]为最少要拿总价值为j时所拿的最小质量
 6     sv = 0;                    //b[i]用来储存m[i]的上一个状态,如果用滚动数组方法就可以去掉b[]数组
 7     for(int i = 1; i <= n; i++) {
 8       cin >> w[i] >> v[i];
 9       sv += v[i];
10     }
11     for(int j = 1; j <= 10000; j++) {
12       m[j] = 1000000001;  //初始化为题目范围内最大值
13       b[j] = m[j];
14     }
15     m[0] = b[0] = 0;
16     for(int i = 1; i <= n; i++) {
17       for(int j = 1; j <= sv; j++) {
18         if(j >= v[i]) m[j] = min(b[j], b[j-v[i]]+w[i]);
19         else m[j] = min(b[j], w[i]);
20       }
21       for(int j = 0; j <= sv; j++) {
22         b[j] = m[j];
23         //b[j] > 1000000000 ? cout << "+ " : cout << b[j] << " ";    //去掉这两行注释可打表结果
24       }
25       //cout << endl;
26     }
27     int big = 1;  //从价值为1开始找所有能拿到的价值
28     while(big <= sv && b[big] <= sw) big++;
29     cout << big-1 << endl;
30   }
31 }
代码实现(点击展开)

相关文章:

  • 2022-12-23
  • 2022-01-18
  • 2022-12-23
  • 2021-07-04
  • 2021-09-04
  • 2019-03-14
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-06
  • 2021-06-01
  • 2019-01-04
相关资源
相似解决方案