[AcWing] 3. 完全背包问题(C++实现)完全背包问题模板题
1. 题目
2. 读题(需要重点注意的东西)
思路:
闫式dp分析法
用闫式dp分析法分析完全背包问题
按以上思路,最朴素的做法
#include<iostream>
using namespace std;
const int N = 1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main(){
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++)
for(int k = 0;k <= j/v[i];k++)
f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
// ------------------核心代码---------------
cout << f[n][m] << endl;
return 0;
}
对核心代码能不能进行优化?
① 将 k 优化掉
对于核心代码部分
for(int i = 1;i <= n;i++)
for(int j = 0;j <= m;j++)
for(int k = 0;k <= j/v[i];k++)
f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
即:
因此,k 就被优化掉了,去除了一层循环
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]>=0) f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
}
② 按 0-1背包问题 的思路再优化成一维
for(int i = 1 ; i <=n ;i++)
for(int j = v[i] ; j <=m ;j++)
f[j]=max(f[j],f[j-v[i]]+w[i]);
最终的结果如 3. 解法。
3. 解法
---------------------------------------------------解法:优化后---------------------------------------------------
#include<iostream>
using namespace std;
const int N = 1010;
int f[N];
int v[N],w[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 = v[i] ; j<=m ;j++)
f[j] = max(f[j],f[j-v[i]]+w[i]);
cout<<f[m]<<endl;
}
可能存在的问题
4. 可能有帮助的前置习题
5. 所用到的数据结构与算法思想
- 动态规划
- 完全背包问题
6. 总结
完全背包问题模板题,理解思想并熟记代码。