完全背包

引入

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 ......你明白的。

posted @ 2019-09-28 14:48  最寻常应是  阅读(135)  评论(1编辑  收藏  举报