点击查看代码
/*
完全背包
题目:https://ac.nowcoder.com/acm/problem/226516
2.讲解算法原理
1.状态表示
f[i][j] 表示:从f[i][j]表示: 从[1, i]区间中挑选, 总体积不超过j的情况下, 所有选法下, 最大价值
2.状态转移方程
不选i --> f[i - 1][j]
f[i][j] 选1个 --> f[i - 1][j - v[i]] + w[i]
选2个 --> f[i - 1][j - 2*v[i]] + w[i]
选k个 --> f[i - 1][j - k*v[i]] + w[i] j >= k*v[i]
要三重循环来解决
优化状态转移方程
原: f[i][j] = max(f[i-1][j], f[i-1][j-v[i]] + w[i], f[i-1][j-2*v[i]] + 2w[i], ......);
f[i][j - v[i]] = max(f[i-1][j-v[i]], f[i-1][j-2*v[i]] + w[i], f[i-1][j-3*v[i]] + 2w[i], .....);
所以: f[i][j] = max(f[i - 1][j], f[i][j - v[i]] + w[i]);
3.初始化
4.填表顺序
从上往下每一行
每一行从左往右
5.最终结果
f[n][v]
6.空间优化
空间优化上:
01 背包: 第二层for循环 -> 从大到小
完全背包: 第二层for循环 -> 从小到大
*/
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1010;
int v[N], w[N];
int f[N][N];
int main(){
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> v[i] >> w[i];
for(int i = 1; i <= n; i++){
for(int j = 0; j <= m; j++){
f[i][j] = f[i-1][j];
if(j >= v[i])
f[i][j] = max(f[i-1][j], f[i][j - v[i]] + w[i]);
}
}
cout << f[n][m] << endl;
// memset:将f数组所有字节赋值为-0x3f(十六进制),等价于十进制的-1061109568
// 作用:初始化所有状态为“不可达”(表示无法恰好装满该容量)
memset(f, -0x3f, sizeof(f));
f[0][0] = 0;// 只有“前0件物品,容量0”的状态是可达的(价值为0)
for(int i = 1; i <= n; i++){
for(int j = 0; j <= m; j++){
f[i][j] = f[i-1][j];
if(j >= v[i])
// 状态2:选第i件物品(完全背包可重复选,所以用f[i][j-v[i]]而非f[i-1][j-v[i]])
// max比较:不选当前物品 vs 选当前物品,取价值更大的那个
f[i][j] = max(f[i-1][j], f[i][j - v[i]] + w[i]);
}
}
if(f[n][m] < 0) cout << 0 << endl;
else cout << f[n][m] << endl;
}
#include <iostream>
#include <algorithm> // max函数需要
using namespace std;
const int N = 1010;
int v[N], w[N]; // v[i]:物品体积,w[i]:物品价值
int f[N]; // 一维数组:f[j]表示容量为j的背包的最大价值
int main(){
int n, m; // n:物品数,m:背包容量
cin >> n >> m;
// 输入物品体积和价值
for(int i = 1; i <= n; i++){
cin >> v[i] >> w[i];
}
// ========== 完全背包一维优化核心 ==========
for(int i = 1; i <= n; i++){ // 遍历每件物品
// 第二层循环:从小到大(j从v[i]到m),允许重复选当前物品
for(int j = v[i]; j <= m; j++){
// 状态转移:f[j] = max(不选当前物品, 选当前物品)
// 不选:f[j](继承上一轮i-1的结果)
// 选:f[j - v[i]] + w[i](当前层已更新的新值,允许重复选)
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
cout << f[m] << endl; // 最终结果:容量m的最大价值
return 0;
}