填坑行动3-背包DP
01背包
01背包可以说是比较经典的一个算法了,它是动态规划的精髓。01背包问题一般是一个这样的问题:
有\(N\)种物品,每种物品的体积分别为\(w_i\),价值分别为\(C_i\)。每种物品只能拿一次。 有一个体积为\(M\)的背包。请问背包能带走最大的价值是多少?
一般人会想到用贪心来做,但是,贪心往往是错误的。看一下一组数据:
\(N=3\)
\(M=5\)
\(W=\{4,3,2\}\)
\(C=\{7,5,3\}\)
显然答案是\(8\),但是用贪心的话答案就是\(7\),所以贪心是错误的。
那么该怎么做呢?\(O\left( 2^n\right)\)肯定会T飞,那么该肿么办呢?
算法解析
令\(f_{i,j}\)为当背包体积为\(j\)的时候,有\(i\)件物品时所带走最大的价值。显然有两种做法:不取、取。
如果不取,那么值就是\(f_{i-1,j}\)。
如果取,那么就要在背包内挖出一块\(w_i\)的空间来存储,还要加上\(c_i\)。值就是\(f_{i-1,j-w_i}+c_i\)。当然还有满足\(w_i\leq j\)
综上得$$f_{i,j}=\max\left(f_{i-1,j},f_{i-1,j-w_i}+c_i\right)$$
复杂度分析
给出一个代码
int f[maxn][maxn];
//读入已省略
for(i=1;i<=m;i++) f[1][i]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(j>=w[i])
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i]);
else f[i][j]=f[i-1][j];
显然我们可以发现空间复杂度为\(O \left(MN\right)\)。时间复杂度也是\(O \left(MN\right)\)。
空间优化
有些时候当\(MN\)比较大的时候,我们需要进行空间优化。
我们发现,要得到\(f_i\)这一行,只需要得到\(f_{i-1}\)就可以了,我们就可以开一个数组int f[2][maxn]就够了。
当然,我们可以直接开一个一维数组,只不过需要从后往前更新,至于原因....我懒得说

浙公网安备 33010602011771号