多重背包的单调队列优化

在直接用多重背包而超时时,我们可以考虑用单调队列来优化。

我们来看一下转移方程:f[i][j]=max(f[i][j],f[i-1][j-w[i]*k]+v[i]*k)

这时我们可以维护f[i-1][j-w[i]*k]+v[i]*k。

当一个f[i-1][l]可以更新f[i][j]时,则有w[i]|(j-l),则有j%w[i]=l%w[i],就说明j与l除以w[i]的余数是一样的。那么我们可以先枚举i,然后枚举余数y,再来更新f,这样就保证了更新问题。

我们设d[][]为单调队列,d[h][1]表示h这个位置的重量,d[h][2]表示h这个位置的价值,则f[i][j]=max(f[i][j],d[h][2]+v[i]*((j-d[h][2])/w[i]))。

这是又有一个问题,我们怎样来判断一个d[h][1/2]有没有过期呢?当一个f[i-1][l]满足j-l>w[i]*t[i],则这个l就是过期的了。所以当j-d[h][1]>w[i]*t[i],那么这个d[h][1/2]就是过期的了。我们每次更新f[i][j]时,都要判断一下队首有没有过期,有的话则更新队首,更新完队首之后才来更新f[i][j]。

在每次更新完f[i][j]之后,我们则要将f[i-1][j]入队。入队时我们从队尾往前找,找到一个价值比f[i-1][j]大的(f[i-1][j]

这就是多重背包的单调队列优化。

总结:

1、单调队列的出入队。

入队:设入队元素为a。从队尾往前找,找到一个比a优的元素,把这个元素后面的所有元素删掉,把a加在这个元素后面。

出队:设出队元素为c,从队头往后找,找到一个比c后入队的元素d,把d之前的都删掉。

2、单调队列的使用。

必须保证数据的单调性,如果这个数据使用不到,而下一个数据可以使用到,那么不能用单调队列(如1407题)。

3、单调队列与单调栈的区别。

单调队列支持入队出队,用于一些会出现因某些元素过期而无法更新的情况。

单调栈只支持入栈用于处理取最优值而没有过期的情况(如1250题)。

你可能感兴趣的:(算法)