湫湫减肥日记(完全背包)
题目
Problem Description
对于吃货来说,过年最幸福的事就是吃了,没有之一!
但是对于女生来说,卡路里(热量)是天敌啊!
资深美女湫湫深谙“胖来如山倒,胖去如抽丝”的道理,所以她希望你能帮忙制定一个食谱,能使她吃得开心的同时,不会制造太多的天敌。
当然,为了方便你制作食谱,湫湫给了你每日食物清单,上面描述了当天她想吃的每种食物能带给她的幸福程度,以及会增加的卡路里量。Input
输入包含多组测试用例。
每组数据以一个整数n开始,表示每天的食物清单有n种食物。
接下来n行,每行两个整数a和b,其中a表示这种食物可以带给湫湫的幸福值(数值越大,越幸福),b表示湫湫吃这种食物会吸收的卡路里量。
最后是一个整数m,表示湫湫一天吸收的卡路里不能超过m。
[Technical Specification]
1. 1 <= n <= 100
2. 0 <= a,b <= 100000
3. 1 <= m <= 100000Output
对每份清单,输出一个整数,即满足卡路里吸收量的同时,湫湫可获得的最大幸福值。Sample Input
33 37 79 91051 15 310 36 87 56Sample Output
10
20
分析
与0-1背包不同的是price[i][j] = max(price[i][j-weight[i]]+value[i],price[i-1][j]);price[i][j-weight[i]]+value[i]在处理后i还是i。
解答(时间O(n*m),空间O(n*m))
/* ------------------------------------------------- Author: wry date: 2022/3/5 15:54 Description: bag ------------------------------------------------- */ #include <bits/stdc++.h> using namespace std; const int MAXN = 1000+10; const int MAXM = 1E5+10; //物品总数 int price[MAXN][MAXM]; //总价值 int weight[MAXN]; int value[MAXN]; int main() { int n,m; //n表示物品数目、m表示背包最大容量 while (cin >> n) { memset(price,0, sizeof(price)); for (int i=1;i<=n;i++) { cin >> value[i] >> weight[i]; } cin >> m; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { if (j<weight[i]) { price[i][j] = price[i-1][j]; } else { price[i][j] = max(price[i][j-weight[i]]+value[i],price[i-1][j]); //判断到底是是牺牲空间给i物品(因为可以无限给)的总价值高,还是保持没有i物品时背包容量是j的价值高 } } } cout << price[n][m] << endl; } return 0; }
优化(时间O(n*m),空间O(m))
(每次处理时只会用到i行和i-1行的值,price[i][j]依赖于price[i-1][j]和price[i][j-weight[i]](更新之后)的值),因为依赖本行的是它更新之后的值,所以需要正向检索。
/* ------------------------------------------------- Author: wry date: 2022/3/5 15:54 Description: bag ------------------------------------------------- */ #include <bits/stdc++.h> using namespace std; const int MAXN = 1000+10; const int MAXM = 1E5+10; //物品总数 int price[MAXM]; //总价值 int weight[MAXN]; int value[MAXN]; int main() { int n,m; //n表示物品数目、m表示背包最大容量 while (cin >> n) { memset(price,0, sizeof(price)); for (int i=1;i<=n;i++) { cin >> value[i] >> weight[i]; } cin >> m; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { if (j>=weight[i]) { price[j] = max(price[j-weight[i]]+value[i],price[j]); } // else { //注释一下,方便理解 // price[j] = price[j]; // } } } cout << price[m] << endl; } return 0; }