完全背包
引入
luogu P1616 疯狂的采药
题解:
先看一下这题:
acwing3. 完全背包问题
有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。
第 i 种物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000
0<vi,wi≤1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
10
分析一下可知,两题很相似,但第二题数据规模小。
(本来就是同一题)
而第二题是一道任何人都看的出来的完全背包问题
~~(很显然是不是,O(∩_∩)O哈哈)~
so,现在的重点就是完全背包问题。(不了解01背包的请来这里)
此类背包问题中,我们的每种物品有无限多个,可重复选取.
类似于01背包,我们依旧需要考虑前i-1件物品的影响.
此时我们依旧可以设得二维状态
f[i][v] 代表用i件物品填充为体积为v的背包得到的最大价值
依旧很容易写出状态转移方程
f[i][v]=max(f[i−1][v],f[i−1][j−k∗c[i]]+k∗w[i])
//其中k是我们需要枚举的物品件数.而我们最多选取 V/c[i]个.
for(int i=1;i<=n;i++)//枚举物品
for(int j=1;j<=V;j++)
for(int k=1;k<=V/c[i];k++)//我们的物品最多只能放多少件.
{
if(k*c[i]<=j)
f[i][j]=max(f[i-1][j],f[i-1][j-k*c[i]]+k*w[i]);
else
f[i][j]=f[i-1][j];
//判断条件与01背包相同.
}
来一波空间限制,目标:空间复杂度O(n)。
同样的,我们去考虑一维状态
(鬼才会考虑
依旧设
f[i] 代表体积为i的时候所能得到的最大价值
与01背包不同的是,我们可以重复选取同一件物品.
此时,我们就需要考虑到前面i-1件物品中是否有已经选取过(其实没必要
即,我们当前选取的物品,可能之前已经选取过.我们需要考虑之前物品对答案的贡献.
因此我们需要顺序枚举.
与01背包一维的写法类似.
for(int i=1;i<=n;i++)//枚举物品
for(int j=c[i];j<=V;j++)//枚举体积.注意这里是顺序/
f[j]=max(f[j],f[j-c[i]]+w[i]);//状态转移.
小结
完全背包也是类似于01背包,应该也算上是它的一种变形.
比较一般的写法是一维写法,希望大家能掌握.
补充:这不是一篇题解,so,emmmmmmm ......你明白的。