多重背包
多重背包,,嗯???怎么和完全背包那么像???
完全一个物品可以选k次,完全有限次的(s+1次选法),就是这个这个区别么???
可能不是一样的吧?我的原理好像弄的不是很清楚,知道看到了这位大佬发的:
************************************************************************************************************************
我感觉多重背包还是应该理解为01背包的扩展,完全背包的“无穷性”导致了跟这俩背包的性质完全不同,特别是完全背包推导那个表达式的时候:
因为
f[i][j]=max(f[i-1][j],f[i-1][j-v]+w,f[i-1][j-2v]+2w,...)
f[i][j-v]=max(f[i-1][j-v],f[i-1][j-2v]+w,...)
又因为物品无穷性,所以上面两式有一一对应的关系
所以
f[i][j]=max(f[i-1][j],f[i][j-v]+w)
这是01背包和多重背包的“有限性”都推导不出的结论~
**************************************************************************************************************************
01背包是每个物品枚举选0个还是1个,多重背包是枚举选0个,1个,2个……
问题二:
怎么样判读从小到大,什么时候判断从大到小;
如果不压缩空间,那么什么顺序都可以。如果压缩了空间,选择的循环顺序要保证代码和压缩前是等价的。比如如果状态计算是f[i, j] = max(f[i - 1, j], f[i - 1, j - v] + w,那么只能从大到小循环,否则计算j时,j - v会先被计算,那么其实算的就是f[i, j] = max(f[i - 1, j], f[i], j - v] + w了,不等价。
这是y总的回答,看完之后我悟了!!!懂了!!!
有 NN 种物品和一个容量是 VV 的背包。
第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 NN 行,每行三个整数 vi,wi,sivi,wi,si,用空格隔开,分别表示第 ii 种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000<N,V≤100
0<vi,wi,si≤1000<vi,wi,si≤100
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
这个数据范围不是很大,100,第一种做法就是暴力啊,原来的完全背包的开始思路也是暴力,不过那题的数据范围太大了,y总选择了优化
#include<iostream> using namespace std; const int N=110; int n,m; int f[N][N],v[N],w[N],s[N]; int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]>>s[i]; for(int i=1;i<=n;i++) { for(int j=0;j<=m;j++) { for(int k=0;k<=s[i]&&k*v[i]<=j;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; }
因为多重背包是01背包的扩展,我看到有直接把完全背包拆成01背包来写的
不吹牛逼,说实话我刚开始学的时候一直把多重背包和完全背包联系起来,导致刚开始拆的时候并没有明白具体意思
但我现在明白了。
就是把后面的s全部化为1,分开来看,比如:
2 5 2
3 1 3
1 1 2
就这个,可以看成:
2 5
2 5
3 1
3 1
3 1
1 1
1 1
懂我意思了吧,嘻嘻
然后这么硬拆虽然暴力血腥,但...不得不说,我喜欢......
#include<iostream> using namespace std; const int N=1e6; long long int f[N],v[N],w[N]; int main(){ int n,m,a,b,c; cin>>n>>m; int t=1; for(int i=1;i<=n;i++) { cin>>a>>b>>c; for(int j=1;j<=c;j++) { v[t]=a; w[t]=b; t++; } } for(int i=1;i<=t;i++) { for(int j=m;j>=v[i];j--) { f[j]=max(f[j],f[j-v[i]]+w[i]); } } cout<<f[m]<<endl; return 0; }
优化成一维,这个我也喜欢,嘻嘻嘻:
(因为y总的j,k的下标我摸不清头脑为什么从0开始,我不理解...)
#include<iostream> using namespace std; const int N=110; int f[N],v[N],w[N],s[N]; int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]>>s[i]; for(int i=1;i<=n;i++) { for(int j=m;j>=0;j--) { for(int k=1;k<=s[i];k++) { if(j>=k*v[i]) f[j]=max(f[j],f[j-k*v[i]]+k*w[i]); } } } cout<<f[m]<<endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具