背包问题
这一个是背包问题的全集,所以还会持续更新
01背包
背包中最经典的一个问题,有n个物品,每一个有价值v和权重w,一个包包容量为x,问取得最大价值为多少?
二维的状态很好设计dp[i][j[表示拿第i个物品,用了j空间的最大值,那么转移方程也就可以得出
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
也就是这个物品不拿所得的价值和拿上这一个物品所获得的价值的最大值,正确性显然。但其实空间复杂度还可以优化,我们发现这是一个之和上一个i有关的转移,所以可以用动态数组滚掉,即dp[i]=max(dp[j],dp[j-w[i]]+v[i])j是对于空间的从大到小枚举,至于为啥要从大到小,当然是为了不让同一层之间的状态相互更新(因为每一个只可以拿一次),还有j要从x一直枚举到w[i]是为了将中间的一些量也附上当前的最优解,以便于下一个状态的dp
完全背包
这个其实比01背包多了一个条件,那就是每个物品可以拿多次。
现在我们去想最简单的状态dp[i][j] 表示拿第i个物品,花j空间可以得到的最优解,那么转移方程也就出来了
*dp[i][j]=max(dp[i-k][j-k*w[i]]+k*v[i],dp[i-1][j])*
这是一个三重循环的过程,其实可以优化一个循环,我们让j=w[i]之后不断加1,那么
*dp[i][j]=max(dp[i-1][j-w[i]]+v[i],dp[i-1][j])*
其中拿上多个物品的操作就在j的不断递增中完成,当然这个也可以用滚动数组优化
*dp[j]=max(dp[j-w[i]]+v[i],dp[j])*
多重背包
其实就是在01背包的基础上加了第i个物品可以取得的s[i]次。
最朴素的想法就是将全部的s个相同的物品都化为不同的,之后就变成的一个简单的01背包问题,但是时间会很慢。
至于用单调队列优化,和二进制优化等以后再去补充,要去补假期作业了啊啊啊啊