动态规划
重新学习动规,又有了新的体会
0-1背包
每种物品只取一次
不优化的表达式是 f[i][j]=max{f[i-1[j],f[i-1][j-w[i]]+c[i]};
f[i][j]与前一行有关所以可以用滚动数组优化(随时更新)
空间优化 滚动数组法
改进后方程 f[j]=max(f[j],f[j-w[i]]+c[i]);
代码如下:
#include<bits/stdc++.h> #define M 2000 using namespace std; int n,m,w[M],c[M]; int f[M]; int main(){ cin>>m>>n; for(int i=1;i<=n;i++){ cin>>w[i]>>c[i]; } for(int i=1;i<=n;i++){ for(int j=m;j>=w[i];j--){//切记是倒叙 重量从大到小枚举 f[j]=max(f[j],f[j-w[i]]+c[i]); } } cout<<f[m]; }
完全背包
数量无限
与01背包滚动数组重量循环(j)的顺序相反;
for(int i=1;i<=n;i++){ for(int j=w[i];j>=m;j++){ f[j]=max(f[j],f[j-w[i]]+c[i]); } }
2022 8.2
P2639 [USACO09OCT]Bessie's Weight Problem G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
01背包
//其实刚开始做这道题时,我以为这和01背包不一样——毕竟只有体积而没有价值。
//但是——我再去想它和01背包有什么相同点时,我发现:只不过01背包是在体积满足时找最大价值,而这道题是在体积满足时找最大体积。
//那么问题来了:假如我们换个思路,将这道题的每个干草也赋予它自己的价值,那岂不是变得和01背包一模一样了??
//那我们赋予每一个干草的价值是什么呢??答案显而易见:就是它自己的体积!!
#include<bits/stdc++.h> #define M 1000001 using namespace std; int n,m; int w[M],c[M]; int f[M]; int main() { cin>>m>>n; for(int i=1;i<=n;i++){ cin>>w[i]; c[i]=w[i]; //不同之处:直接赋值而非输入! } for(int i=1;i<=n;i++){ for(int j=m;j>=w[i];j--){ f[j]=max(f[j],f[j-w[i]]+c[i]); } } cout<<f[m]; }
多重背包
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
例题庆功会 转化成01背包进行求解
滚动数组法
#include<iostream> #include<cmath> #define N 10001 using namespace std; int n,m; int s[N],w[N],f[N],c[N] ; int main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>w[i]>>c[i]>>s[i]; for(int i=1;i<=n;i++) for(int j=1;j<=s[i];j++) //s[i]个物品是i的01背包 for(int k=m;k>=w[i];k--) f[k]=max(f[k],f[k-w[i]]+c[i]); cout<<f[m]; }