【笔记+代码】背包问题
来源:互联网 发布:创维网络电视怎么样 编辑:程序博客网 时间:2024/05/21 06:33
- 01背包
- 板子
- 超大01背包
- 完全背包
- 多重背包
- 二进制拆分
- 混合背包
- 二维费用背包
- 分组背包
- 有依赖背包问题
n个物品 背包容量W
w[i] 费用,v[i] 价值;
01背包
每件物品选或不选。
板子:
void zerone(int wei,int val){ for(int j=W;j>=wei;j--) d[j]=max(d[j],d[j-wei]+val);}for(int i=1;i<=n;i++) zerone(w[i],v[i])
超大01背包
每个物品只能拿一次,物品数量M<=100,背包容量T<=10^9,每个物品的价值<=100,每个物品的重量<=10^9
将dp数组第二维变为价值,存储达到价值j所需的最小重量
dp[i][j]=min(dp[i][j],dp[i-1][j-v[i]]+w[i])
在dp[n][j]<=W里找最大的j
完全背包
每件物品可以选无数次。
void wanquan(int wei,int val){ for(int j=wei;j<=W;j++) d[j]=max(d[j],d[j-wei]+val);}for(int i=1;i<=n;i++) wanquan(w[i],v[i])
数竞大佬的证明思路①dp[i][j]max=dp[i-1][j-k*w[i]]+k*v[i] 0<=k②dp[i][j]max=dp[i-1][j-w[i]-t*w[i]]+t*v[i]+v[i] 0<=t,1<=k dp[i-1][j] k==0③dp[i][j-w[i]]max=dp[i-1][j-w[i]-t*w[i]]+t*v[i] 0<=t将③带入②dp[i][j]max = dp[i-1][j] dp[i][j-w[i]]+v[i]
多重背包
每件物品可以选固定数量次。
二进制拆分
void duochong(int wei,int val,int num){ if(num*wei>=W) { wanquan(wei,val); return; } int k=1; while(k<num){ zerone(wei*k,val*k); num-=k; k*=2; } zero(wei*num,val*num); return ;}for(int i=1;i<=n;i++) duochong(w[i],v[i],m[i])
时间复杂度 m*xigema(logk)
二进制拆分的可行性证明(不严格):
k=2^0+2^1+2^2+………2^x+p;
k=(111…….1)(2进制)+p;
那么从0–1111111….1的数,可由2的次幂的选否表示出来。
p<11111…..11(p<2^(x+1)),p+111…111=k;
从11111…..1+1—–k,固定选p,那么要凑的质量-p一定小于1111..1,
有上述结论可知,这个数是可以凑出来的。
证毕;
混合背包
每个物品可以选一件,无数件或给定数量件
解法:对于每件物品,判断是01,完全,多重,分别计算。
for(int i=1;i<=n;i++){ if(wanquan) wanquan(w[i],v[i]); if(01) zerone(w[i],v[i]); if(duochong) duochong(w[i],v[i],m[i]);}
二维费用背包
对于每个物品,有两种费用,每个费用都有最大值;
隐含方式:
最多取m件,这是件数就是另一个费用,每个物品此费用为1
for(int i=1;i<=n;i++){ for(int j=W;j>=w[i];j--){ for(int k=U;k>=u[i];k--){//另一个价值u dp[j][k]=max(dp[j][k],dp[j-w[i]][k-u[i]]+v[i]); } }}完全jk顺序循环,多重拆分;
分组背包
所有物品分为k组,每组中至多选择一个物品;
for(int i=1;i<=k;i++) //每组内部 for(int j=W;j>=0;j--)//背包总重量 for(p)//p是该组内部的物品 dp[j]=max(dp[j],dp[j-w[p]]+v[p]);
正确性证明:
一开始以为只要背过代码就可以,结果度娘一搜,发现背包九讲第一版中居然有错误。
http://www.cppblog.com/Onway/archive/2010/08/09/122695.html
%这位不知名大神。
递推式dp[j]=max(dp[j],dp[j-w]+v]
循环顺序 组别,质量,组内物品。
对于每个组内,对每一个质量进行循环,由于j是逆序,dp[j]是上一组决策的结果。
同样由于j是逆序,质量为j-w的背包还未在(第一层循环)本组中决策,故j-w也是上一组决策的结果,保证滚动数组的正确性。
有依赖背包问题
- 【笔记+代码】背包问题
- 背包问题--代码
- 背包问题--代码
- 背包问题代码
- 背包问题java 代码
- 01背包问题代码
- 背包问题的代码
- 背包问题学习笔记
- 0-背包问题笔记
- [笔记]: 背包问题
- 背包问题九讲笔记_01背包
- 背包问题九讲笔记_01背包
- 背包问题九讲笔记_01背包
- 背包九讲笔记-01背包问题
- 背包九讲笔记-完全背包问题
- 背包问题九讲笔记_01背包
- 背包问题九讲笔记_01背包
- 背包问题九讲笔记_01背包
- NYOJ68
- Double类型运算
- bzoj 3392: [Usaco2005 Feb]Part Acquisition 交易 最短路
- 287. Find the Duplicate Number
- Filter过滤器
- 【笔记+代码】背包问题
- python -集合
- Spring+SpringMVC整合----配置文件
- spark中 transformation和action介绍
- 数据挖掘之数据准备
- 搭建Linux内核开发环境
- 一款优雅的干货集中营android客户端、实现沉浸式状态栏
- springMVC跨域请求配置前置增强器
- mybatis(1)