原版
背包问题九讲 2.0 alpha1 崔添翼 (Tianyi Cui, a.k.a. dd_engi)
背包九讲学习笔记 第一讲 01背包
背包九讲学习笔记 第二讲 完全背包问题
背包九讲学习笔记 第三讲 多重背包
背包九讲学习笔记:第四讲-混合三种背包问题 第五讲-二维费用的背包问题
背包九讲学习笔记 第六讲-分组的背包问题
背包九讲学习笔记 第七讲-有依赖的背包问题 第八讲-泛化物品
背包九讲学习笔记 第九讲 背包问题问法的变化
1. 01背包
有N件物品和一个容量为V 的背包。放入第i件物品耗费的空间是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。
for(int i=1;i<=n;i++)
for(int j=v;j>=volume[i];j--)
dp[j]=max(dp[j],dp[j-volume[i]]+value[i]);
满包问题
初始化为0,max变为加
2. 完全背包
有N种物品和一个容量为V 的背包,每种物品都有无限件可用。放入第i种物品的耗费的空间是Ci,得到的价值是Wi。求解:将哪些物品装入背包,可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。
for(int i=1;i<=n;i++)
for(int j=volume[i];j<=v;j++)
dp[j]=max(dp[j],dp[j-volume[i]]+value[i]);
3. 多重背包
二进制优化
int v=read(), n=read();
int dp[M]={}; //dp[j]表示j体积能装的最大价值, 已经空间优化
for(int i=1; i<=n; ++i)
{
int vol=read(), val=read(), num=read(); //体积,价值,数量
for(int k=1; k<num; num-=k,k<<=1)
for(int j=v; j>=k*vol; --j)
dp[j] = max(dp[j], dp[j-k*vol]+k*val);
for(int j=v; j>=num*vol; --j)
dp[j] = max(dp[j], dp[j-num*vol]+num*val);
}
int v=read(), n=read();
int dp[M]={};
for(int i=1; i<=n; ++i)
{
int vol=read(), val=read(), num=read(); //体积,价值,数量
for(int k=0; k<vol; ++k) //枚举体积的余数
{
int a[M], b[M], l=0, r=0; //下标, 值, 队头, 队尾, 左闭右开
for(int j=k; j<=v; j+=vol)
{
int y = dp[j] - j/vol*val; //当前体积的贡献值
while(l<r && y>=b[r-1]) r--; //入队
a[r] = j; b[r++] = y;
while(a[l]<j-num*vol) ++l; //出队
dp[j] = b[l] + j/vol*val; //选择最大值
}
}
}
printf("%d\n",dp[v] );
4. 混合三种背包
可以都按多重解,设置好件数就行。
5. 二维费用背包
二维费用的背包问题是指:对于每件物品,具有两种不同的空间耗费,选
择这件物品必须同时付出这两种代价。对于每种代价都有一个可付出的最大值
(背包容量)。问怎样选择物品可以得到最大的价值。
设这两种代价分别为代价一和代价二,第i件物品所需的两种代价分别
为Ci和Di。两种代价可付出的最大值(两种背包容量)分别为V 和U。物品的
价值为Wi。
新加的一维一般为件数,注意遍历顺序要写对。
for(int i=1;i<=n;i++)
for(int j=v;j>=volume[i];j--)
for(int k=w;k>=weight[i];k--)
dp[j][k]=max(dp[j][k],dp[j-volume[i]][k-weight[i]]+value[i]);
cty : 当发现由熟悉的动态规划题目变形得来的题目时,在原来的状态中加一维
以满足新的限制是一种比较通用的方法。希望你能从本讲中初步体会到这种方
法。
6. 分组背包
有N件物品和一个容量为V 的背包。第i件物品的费用是Ci,价值是Wi。这
些物品被划分为K组,每组中的物品互相冲突,最多选一件。求解将哪些物品
装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
遍历顺序kji
for(int k=1;k<=p;k++)
for(int j=v;j>=0;j–) //此处遍历顺序与物品种类有关
for(int i:part[k])
dp[j]=max(dp[j],dp[j-volume[i]]+value[i]).
8.泛化物品
考虑这样一种物品,它并没有固定的费用和价值,而是它的价值随着你分
配给它的费用而变化。这就是泛化物品的概念。
泛化物品的和:
f
v
=
m
a
x
k
=
0
v
(
h
k
+
l
v
−
k
)
f_v = max_{k=0}^v(h_k + l_{v − k} )
fv=maxk=0v(hk+lv−k)
7.有依赖的背包问题
这种背包问题的物品间存在某种“依赖”的关系。也就是说,物品i依赖于
物品j,表示若选物品i,则必须选物品j。为了简化起见,我们先设没有某个物
品既依赖于别的物品,又被别的物品所依赖;另外,没有某件物品同时依赖多
件物品。
确定每组物品的主件k后,对主件k的“附件集合”先进行一次01背包,求得主件k的物品组泛化物品。再利用分组背包来求解。
9. 背包问题问法的变化
输出方案
输出字典序最小的方案
求方案数
求最优方案数
求第k优解
留坑