背包dp
1. 例题1: 背包模板/采药
同样的思考方式:状态是什么,方程是什么
状态: 表示在 个物品中用 元选的最优解
方程: 可以用 元来换取 的最优解
初始值:
代码:
for(int i=1;i<=n;i++) dp[i][0]=0;
for(int i=1;i<=n;i++)
for(int j=w[i];j<=m;j++)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
但是有定义有二维,考虑优化一层。
方法一:交替dp
我们发现,只需要存 就行了。
所以可以开 dp[2][n];
每一次存就可以了。
核心代码:
int now=0,old=1;
for(int i=1;i<=n;i++)
{
swap(now,old);
for(int j=w[i];j<=m;j++)
自己想方程;
}
方法二:滚动数组
刚刚还是用了二维啊!!!
似乎一维只需要去第一维便可以呀!!!
for(int i=1;i<=n;i++)for(int j=w[i];j<=t;j++)f[j]=max(f[j],f[j-w[i]]+v[i]);
然后发现你挂了(不会有人复制了吧)
.
你会发现,只需要稍微改变一下顺序就可以了。不理解的在纸上写一下dp过程。
for(int i=1;i<=n;i++)
for(int j=t;j<=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
2. 例题2:完全背包模板/疯狂的采药
完全背包和 背包完全相反,刚刚你写错的代码就是AC正解……
for(int i=1;i<=n;i++)
for(int j=w[i];j<=t;j++)
f[j]=max(f[j],f[j-w[i]]+v[i]);
3. 例题3:多重背包/迪奥娜的难题(数据未完成)
这里可以先自己思考一下,代码如下:
for(int i=1;i<=n;i++)
for(int j=0;j<=v;j++)
for(int k=0;k<=s[i]&&k*c[i]<=j;k++)
dp[i][j]=max(dp[i][j],dp[i-1][j-kc[i]]+kw[i]);
but 这样子dp数组根本存不下来,我们得了解一下二进制优化:
首先,我们可以将它分成 份,接着并可以 背包
这样子时间复杂度变为了 ,还是会 T。
我们可以使用二进制优化。
因为 ,所以我们拆的时候就这么拆就行了
4. 例题4:混合背包/樱花
似乎很难诶...
stop,不就是把三种dp结合在一起吗?
01背包可以看成只有一个的多重背包。
伪代码如下:
for(int i=1;i<=n;i++)
if(t[i]==0)
完全背包
else
多重背包
代码是不可能给你的...

浙公网安备 33010602011771号