背包九讲

考前两天,再看一下dd的背包九讲,巩固一下。(毕竟我DP实在是太弱了)


01背包

模型

(N)个物品,每个费用为(V_i),价值为(W_i),总钱数为(C),求最大价值。

子状态

(f[i][j])表示前(i)件总钱数为(j)情况下的最大价值。

朴素转移

朴素转移每一次讨论当前物品到底取不取。

状态转移方程为(f[i][j]=min(f[i-1][j],f[i-1][j-w[i]]+v[i]))

空间优化

由于每一层的取值只需要依赖上一层的值,因此在实现的时候可以省略第一维。

但是这个时候原第二位的遍历需要采取倒叙,这样就可以保证我们遍历到(f[j])的时候(f[j-w[i]])里面保存的是原来(f[i-1][j-w[i]])的值。

伪码实现


FOR i from 0 to C
    f[0][i]=0
FOR i from 1 to n 
    FOR j from Vi to C
        f[i][j]=min(f[i-1][j],f[i-1][j-w[i]]+v[i])



FOR i from 0 to C
    f[i]=0
FOR i from 1 to n
    FOR j from C downto Vi
        f[j]=min(f[j],f[j-w[i]]+v[i])

细节

如果题目不要求背包要恰好装满,那么照常初始化。

但如果要求背包恰好装满,那么(f[1])(f[C])都必须设为(-INF)(因为只有(f[0])是刚好装满),而最后的答案为(f[C])


完全背包

模型

(N)种物品,每种都有无限个,其余同01背包。

子状态

考虑01背包的空间优化写法,我们发现,之所以不可以顺序写,是因为这样同样的一件物品可能会被取多次。

这恰好是完全背包问题所允许的。

因此完全背包问题采用顺序的写法。

子状态为(f[i]),表示容量为(i)的背包最多能放多少个。

转移

上面说了

代码实现


FOR i from 0 to C
    f[i]=0
FOR i from 1 to n
    FOR j from Vi to C
        f[j]=min(f[j],f[j-w[i]]+v[i])

原文地址:https://www.cnblogs.com/ilverene/p/9929026.html