背包DP:背包九讲学习记录
01背包:
{
v c[i] w[i]
二维:
f[i,j]=将前i个物品恰放于容量为v的背包中的最大价值
~~~~~~
不选第i个物品 f[i,j]:=f[i-1,j];
选第i个物品 f[i,j]:=f[i-1,j-c[i]]+w[i];
f[i,j]:=max{f[i-1,j],
f[i-1,j-c[i]]+w[i]}
一维:
f[v]=恰放于容量为v的背包中的最大价值
f[v]:=max{f[v],f[v-c[i]]+w[i]}
for i:=1 to n do
for j:=v downto 0 do
f[j]:=max{f[j],f[j-c[i]]+w[i]}
or
for i:=1 to n do
for j:=v downto 0 do
f[i,j]:=max{f[i-1,j],f[i-1,j-c[i]]+w[i]}
————————————————
misunderstanding:
注意f[i][v]有意义当且仅当存在一个前i件物品的子集,
其费用总和为v。所以按照这个方程递推完毕后,
最终的答案并不一定是f[N] [V],
而是f[N][0..V]的最大值。
如果将状态的定义中的“恰”字去掉,
在转移方程中就要再加入一项f[i][v-1],
这样就可以保证f[N] [V]就是最后的答案。
————————————————
}
完全背包
{
有n种物品和一个容量为v的背包
第i件物品的费用为c[i]
价值为w[i]
每件可取无数件
f[i,j]=将前i个物品恰放于容量为v的背包中的最大价值
~~~~~~
f[i,j]:=max{f[i-1,j-k*c[i]]+k*w[i] | 0<=k*c[i]<=v}
优化:
1:如果物品i与物品j c[i]<c[j] and w[i]>w[j],就把j去掉
2:转化为01背包
由于第i件物品最多选v/c[i]件,那就把第i件物品转化为
(v/c[i])件i物品
基本思路:将一种物品拆成多种物品
O(n*v)
for i:=1 to n do
for j:=0 to v do
f[i,j]:=max{f[i-1,j],f[i-1,j-c[i]]+w[i]}
or
for i:=1 to n do
for j:=0 to v do
f[j]:=max{f[j],f[j-c[i]]+w[i]}
misunderstanding:
O(n*v)的算法原理没搞懂
}
多重背包
{
有n中物品和一个容量为v的背包,
第i种物品费用为c[i]
价值为w[i]
最多选n[i]件
第一个思路:
对于第i个物品有(n[i]+1)个决策
......不选、选一件、选两件、... 、选n[i]件
so,可得转移方程
f[i,j]:=max{f[i-1,j-k*c[i]]+w[i]*k | 0<=k<=n[i]}
复杂度 O(v*siga(n[i]))
简单的第二个思路
转化为01背包。把第i个物品转化为n[i] 件i物品
然后就是一个01背包
misunderstand:
关于二进制以及单调队列的东西
}
混合背包
{
将以上三种背包混合,有的物品只能取一种,
有的物品可取无限次,有的可取次数由一个上限
感觉好像不算太难
for i:=1 to n do
begin 如果是01背包
for j:=v downto 0 do
f[i,j]:=max{f[i-1,j],f[i-1,j-c[i]]+w[i]};
如果是完全背包
for j:=0 to v do
f[i,j]:=max{f[i-1,j],f[i-1,j-c[i]]+w[i]};
如果是多重背包
for j:=v downto 0 do
begin for k:=0 to v/c[i] do
if f[i,j]<f[i-1,j-k*c[i]]+(w[i]*k)
then f[i,j]:=f[i-1,j-k*c[i]]+(w[i]*k)
end;
end;
}
二维费用的背包
{
问题:对于每种物品,有两个代价,
如果选择这种物品,就要支付这两种代价
a[i],b[i] 代价
v[i] 利益
f[i,j,k] 前i件物品支付j,k的代价之后得到的最大利益
f[i,j,k]:=max{f[i-1,j,k],
f[i-1,j-a[i],k-a[i]]+v[i]}
for i:=1 to n do
for j:=v downto 0 do
f[i,j,k]:=max{f[i-1,j,k],
f[i-1,j-a[i],k-a[i]]+v[i]}
常以隐含条件出题
01背包中限制选取数量
//每个物品的b[i]=1//
}
**
分组背包
{
有n件物品,和一个容量为v的背包
划分为k组,每组的物品互相冲突{只选一件}
f[i,j]{前i组物品花费代价为j所获得的最大利益}
f[i,j]:=max{f[i-1,j],f[i-1,j-v[i][k]] | 0<=k<=第i组物品的数量 }
f[j]:=max{f[j],f[j-v[i][k] | 0<=k<=第i组物品的数量 }
for i:=1 to n do
for j:=v downto 0 do
for k:=1 to 第i组物品的数量
}
***
有依赖的背包
{
题意:
物品间存在依赖关系
简化:
1、不存在一件物品依赖多件物品
2、不存在一件物品及依赖其他物品,有被别的物品锁依赖
将不被其他物品所依赖的物品叫 主件
依赖其他物品的叫 附件
所有物品由{有一个主件和多个附件}集合组成
假设有n个集合 {有c[i]个附件}
选择方案:1、不选主件
2、只选主件
3、选主件和一个附件 {c[i]种}
4、选主件和两个附件 {}
5、选主件和三个附件 {}
.
.
.
.
.
c[i]+2、 选主件和c[i]个附件 {1种}
总数是2^c[i]+1
将一件物品扩展为2^c[i]+1件
一个简单的优化:对于一个集合中代价相同的组合,只保留一个利益最大的
}
***
泛化背包
{
题意:
在一个背包容量为v的背包问题中,泛化物品的v和w有一个严格的关系
当分配给他的费用为w[i]时,利益为v[i]
感觉它的意思是每一种背包问题都可以看作是一种泛化背包
01背包,当代价是w[i]时,利益是v[i]; 其余的时候v[i]=0
完全背包,当代价w=w[i]*k{0<=k<=V/w[i]} 利益是v[i]*k;
其余的时候v[i]=0;
多重背包,当代价w=w[i]*k{0<=k<=n[i]} 利益是v[i]*k
其余的时候v[i]=0;
当只有两件泛化物品时 q,p
f[i]=q[i]+p[v-i];
最大利益是 max{f[i]} {0<=i<=v}
}