第一部分:01背包初步理解
刚开始学01背包一头雾水,听不明白,但慢慢的随着查资料,刷题,逐渐得到了一些关键的知识点,才有点顿开的感觉。
1:动态方程 dp[i][j]=max(dp[i-1][j-w[i]]+c[i],dp[i-1][j]) 我逐渐理解到这个方程为什么要这么写是从j-w[i]开始的。
2:j代表背包容积,j-w[i]代表剩余背包容积,dp[i][j]=max(dp[i-1][j-w[i]]+c[i],dp[i-1][j]),这个方程是建立在j>=w[i]的基础上的,如果j<w[i],dp[i][j]=dp[i-1][j],也就是上一个状态,从0开始最初状态是0,dp[i][j]所以会被保存下来。
3:所以dp[i-1][j-w[i]]其实是看剩下的容积能否放下上一个状态的物体,因为上一个状态被保存下来了,所以我们可以知道能否放下,如果可以放下,也就是剩余容积放了上一个物体的价值,dp[i-1][j-w[i]]+当前即将要放的c[i],如果不可以放下,就是剩余的容积对应的上一个状态态没有放上一个物体的价值+当前c[i],这里的比较。
4:也就是把背包里面能拿出来的拿出来,然后背包整体减少后的价值加上c[i],然后与没有拿出背包里的物体,背包保持上一个状态的价值做对比,谁大要谁。然后保存下来。//记忆化
5:看一下局部代码:
for(int i=1;i<=n;i++)//i代表物体的种类,并且每种物体只有一个
{
for(int j=w[i];j<=m;j++)//这样写是因为上面有个if判断if(j<w[i])dp[i][j]=dp[i-1][j],这样写更简便就不需要做判断了,j<w[i]的地方依然保持上一个状态,j>=w[i]的地方根据max()函数来判断是否要保持原状态
{ dp[i][j]=max(dp[i-1][j-w[i]]+c[i],dp[i-1][j]);
}
}
第二部分:将二维数组优化维一维数值
/*理解上面的就好理解下面的了*/
dp找的是前一个状态,二维数组刚好可以将前一个状态表现在dp[i-1[j]中,但这样用了二维数组对空间就不太节约了,所以我们要优化成一维数组所以就需要将前一个状态弄到一维数组中即找没有更新的状态,所以我们可以逆序来找
/*也就是说将j=n背包容量从最大开始找向前找状态,前面的状态都还没有更新所以所以就可以继续用一维数组每次都在一维数组中找到前一个状态。而如果是按递增的顺序去的化每次j-w[i]都是找到了更新后的状态,我们要找的上一个状态,而不是更新后的状态*/
看下代码:
for(int i=1;i<=n;i++)
{
for(int j=m;j>=w[i];j--)
{
dp[j]=max(dp[j-w[i]],dp[j]);//理解和上面相同自己体会
}
}
01背包深入理解,以及优化
最新推荐文章于 2022-01-18 23:34:26 发布