如果看不懂不妨看看下面的
#include<bits/stdc++.h>
using namespace std;
int w[105] = { 0 }, va[105] = { 0 }, f[1005] = {0};
int main() {
int t, n;
cin >> t >> n;
for (int i = 1; i <= n; i++)
cin >> w[i]>>va[i];
for (int i = 1; i <= n; i++)//从第一件物品开始转移
for (int j= t;j>=w[i];j--)
f[j] = max(f[j],f[j-w[i]]+va[i]);
cout << f[t];
return 0;
}
如何理解
for (int i = 1; i <= n; i++)//从第一件物品开始转移
for (int j= t;j>=w[i];j--)
f[j] = max(f[j],f[j-w[i]]+va[i]);
f [ i ] 为在 i 时刻你采了多少价值的药,假设你有6秒时间采药,一开始你看着药草傻站着,什么都没采,所以在第0,1,2,3,4,5,6秒你采的药的价值都为0,假设你采了第一个药,第一个药草价值为2,花时为3,在第0秒采的话, 那你就用你在第0秒采的药的价值加上假设采了第一个药的价格来更新在第三秒采的药的价格很明显第0所采的药的价格为0f[3]=max(f[0]+3,f[3])=3,如果你 是从前往后更新 就会在f[6]时,f[6]=max(f[6],f[3]+3), 就是你用第三秒采药的价格来更新第六秒所采药草的价格,而这是在 第一个药草这里,即第一轮更新,这样导致你第三秒采了一个然后接着第三秒又花了三秒来采第一个药草,就是重复采药,不符合题意,但这是完全背包的写法
后来你又采第二个药价值为3,花时为1,为了从前往后更新,那你就先用你在第3秒采的药的价值加上假设采了第二个药的价格来更新在第4秒采的药的价格f[4]=max(f[3]+3,f[4])=6
然后假设后面你发现有两个草第三个药草价值为2,花时为4,第4个药草价值为5,花时为2
在第三轮首先第6秒会被第四秒的价格更新f[6]=max(f[4]+4,f[6])=10
第5秒会被第3秒的价格更新f[5]=max(f[3]+4,f[5])=7
第2秒会被第0秒的价格更新f[2]=max(f[0]+4,f[2])=4
在第三轮首先第6秒会被第四秒的价格更新f[6]=max(f[4]+5,f[6])=11
第5秒会被第3秒的价格更新f[5]=max(f[3]+4,f[5])=8
第2秒会被第0秒的价格更新f[2]=max(f[0]+4,f[2])=5
然后最大值就是11
完全背包就不讲了,就是对任意一个物品,可以无限取,就是更新变成了从前往后
for (int i = 1; i <= n; i++)//从第一件物品开始转移
for (int j= 0;j<=t;j++)
f[j] = max(f[j],f[j-w[i]]+va[i]);