0/1背包问题是动态规划中最为经典的题目。
有n个物品,已知各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
样例输入:
3 8
3 3
5 4
5 5
样例输出:
8
- 思路:
动态规划,列表为先
接下来需要寻找规律,关键节点为:
当可以放入选定物品时进行价值比较。
如【5,2】:
当前可以放入物品2,这时需要比较两者价值,则比较【5,1】与【0,1】+自身价值
【5,1】是指如果不替换的价值;而【(5 - 5),1】是指腾出物品所需空间后剩余价值(第一个5为当前背包容量,而第二个5则是需要腾出的5个空间),加上放入物品价值就是总价值。
(0行0列在表格中省略,价值均为0)
因此得到思路(关键判断式):
f[i][j] = max(f[i - 1][j - w[i]] + c[i],f[i - 1][j]);
f[i][j] : 当前所求价值; f[i - 1][j - w[i]] : 腾出空间后所剩价值
c[i] : 指定物品价值; f[i - 1][j] : 不放入的价值
- 代码
w,c数组分别储存重量和价值
#include <bits/stdc++.h>
using namespace std;
int w[200],c[200],f[200][200];
int main(){
// ......
cout << f[n][m];
return 0;
}
接下来是主函数
m表示背包总容量 n表示物品总数
int i,j,m,n;
cin >> m >> n;
for (i = 1; i <= n; i++){
cin >> w[i] >> c[i];
}
核心判断
for (i = 1; i <= n; i++){
for (j = 1; j <= m; j++){
if (j >= w[i]){
f[i][j] = max(f[i - 1][j - w[i]] + c[i],f[i - 1][j]);
} else {
f[i][j] = f[i - 1][j];
}
}
}
如果可以放入物品则比较价值;若不能则延续原价值。
总代码
#include <bits/stdc++.h>
using namespace std;
int w[200],c[200],f[200][200];
int main(){
int i,j,m,n;
cin >> m >> n;
for (i = 1; i <= n; i++){
cin >> w[i] >> c[i];
}
for (i = 1; i <= n; i++){
for (j = 1; j <= m; j++){
if (j >= w[i]){
f[i][j] = max(f[i - 1][j - w[i]] + c[i],f[i - 1][j]);
} else {
f[i][j] = f[i - 1][j];
}
}
}
cout << f[n][m];
return 0;
}