多重背包优化一
•看做有N组物品,放入容量为j的背包,对于每组物品,选择放入的数量k(0…n[i])
•对于第i种物品,放入容量为j的背包
f[j+k*c[i]] = max{f[j+k*c[i]],f[j]+k*w[i]}
•j= 0: c[i], 2*c[i], 3*c[i],..., n[i]*c[i]
•j= 1: 1+c[i], 1+2*c[i]...
•j= c[i]: 2*c[i],3*c[i]...
•如果f[c[i]]中放入了c[i],j=0 与 j=c[i]完全重复
•一种优化,如果f[j]被更新过了,那就跳过此次循环
多重背包优化二(仅限于可行性问题)
•和完全背包相比,物品的数量是有限的,尽量节省地使用物品i
•g[i][j],记录物品i,在容量为j,达到最优值时,使用的最少数量
•如果之前物品能够在容量为j时达到最优值,那就不用使用物品i了
•f[i][j]=max{f[i-1][j],f[i][j-c[i]]+w[i]}
•g[i][j]= 0, f[i][j] =f[i-1][j]
• g[i][j-c[i]]+1, f[i][j] = f[i][j-c[i]]+w[i]
•
•fori = 1 to N
• g[0…V] = 0
• for j = 0 to V
• if g[j-c[i]] + 1 > n[i] continue
• if f[j-c[i]]+w[i] > f[j]
• f[j] = f[j-c[i]]+w[i]
• g[j] = g[j-c[i]] + 1
•
•时间复杂度O(NV)
开始以为这种想法可以用于求最值的多重背包,后来学长给出反例:
”如果 g[j - v[i]] + 1 > c[i]
这个时候 不能从转移 dp[j - v[i]] + w[i]
这个一定是对的么
万一 dp[j - v[i]] 的最优值 是用了 c[i] 个得到的
但是如果我在 dp[j - v[i]] 处用用了 c[i] - 1 个
那个不是最优值
但是 转移到 dp[j - v[i]] + w[i]
可以得到比 dp[j] 更优的怎么办呢 “
...还真没办...写下交了道水题,果断WA掉了...
想想,这种转移违背了最优子结构的性质,子问题最优,但原问题不定最优
多重背包优化三
就是比较常见的单调队列优化
单调队列优化,一般就是证明,对于i ,任意的j<i, 都有F(i) > F(j),则小于i的都不用考虑,从而减少枚举的决策数
详细讲解见http://www.cppblog.com/flyinghearts/archive/2010/09/01/125555.html
更多的关于单调队列优化的见http://wenku.baidu.com/view/ef259400bed5b9f3f90f1c3a.html