单调队列优化多重背包python
时间: 2025-02-17 20:19:51 浏览: 50
### 单调队列优化多重背包问题的Python实现
对于多重背包问题,当物品数量较大时,朴素解法的时间复杂度过高。为了提高效率,可以采用单调队列来优化求解过程[^2]。
#### 原理说明
在处理第`i`种物品时,设该物品的价值为`v[i]`,体积为`w[i]`,最多可以选择的数量为`s[i]`。假设当前考虑容量范围是从`j-w[i]*k`到`j`(其中`0≤k<s[i]+1`),那么在这个范围内选择若干件此物品所获得的最大价值可以通过动态规划的状态转移方程计算得出:
\[ dp[j]=\max(dp[j],dp[j-k*w[i]]+k*v[i]) \]
这里存在重复子结构的特点,即随着`k`增加,新的状态总是基于旧的状态更新而来。利用这一点特性,引入滑动窗口最大值的思想——每当遍历一个新的位置`j`时,只需要关注那些能够影响当前位置决策的有效历史信息即可;而这些有效的历史信息正好可以用一个维护着最近若干个元素及其对应索引的双端队列(`deque`)表示出来。
具体来说就是保持一个按顺序存储满足条件的位置列表,并且保证这个列表内的每一个成员都严格优于它后面的成员(这里的优劣关系取决于题目中的定义)。这样做的好处在于每次查询最优解的时候只需访问一次队首元素就能得到答案,从而大大降低了时间开销。
#### Python代码示例
下面给出一段具体的Python代码用于解决上述提到的问题:
```python
def multi_pack(n, V, v, w, s):
from collections import deque
f = [float('-inf')] * (V + 1)
f[0] = 0
for i in range(1, n + 1):
q = deque()
for j in range(V // w[i]):
cur_j = min(j * w[i], V)
# 清除不在窗口内的元素
while q and q[0][0] < j - s[i]:
q.popleft()
# 更新f[cur_j]
if not q or q[0][1] >= f[cur_j]:
f[cur_j] = max(f[cur_j], q[0][1] if q else 0) + v[i] * ((cur_j % w[i] == 0) ^ bool(q))
# 维护单调递减队列
while q and q[-1][1] <= f[cur_j]:
q.pop()
q.append((j, f[cur_j]))
return max(f[V//w[i]*w[i]:])
# 测试数据
n = 3 # 物品数目
V = 8 # 背包总容量
v = [6, 3, 5] # 各类物品单位重量下的价值
w = [2, 2, 3] # 各类物品每件占用的空间大小
s = [4, 2, 3] # 对应种类物品可选数量上限
print(multi_pack(n,V,v,w,s))
```
这段程序实现了通过单调队列的方式快速找到每个阶段的最佳方案并最终返回整个过程中所能达到的最大收益值。
阅读全文
相关推荐

















