算法题总结-分组背包
原题
有 N 件物品和一个容量为 V 的背包。第 i 件物品的费用是 Ci,价值是 Wi。这些
物品被划分为 K 组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包
可使这些物品的费用总和不超过背包容量,且价值总和最大。
由于截止目前,没有刷到对应的经典题目,以下以依赖背包的转化题目进行解析
https://www.cnblogs.com/dengliang356a/p/17473023.html
基本解析过程:
分组背包问题,可以简化为一种逻辑,遍历每一个物品组,那么对于 第k组物品组,策略为选择组内一种物品或者一种都不要[依赖背包转化的问题就是,选择一种策略或者一种策略也不选]
核心转移方程:
F[k, v] = max{F[k − 1, v], F[k − 1, v − Ci] + Wi| item i ∈ group k}
方程含义,k-1组容量V的最优解,与 k-1组容量 v − Ci最优解加上第k组物品以后的最优解进行比较,从而获得 前K组的容量V最优解
因此,仅需要按K、V双重循环,每次循环将每个策略往结果F里面进行叠加
注意事项:
1、容量必须是降序,max比较中,F[k − 1, v − Ci]、F[k − 1, v]初始态必须是0
1.1、容量升序,F[k − 1, v − Ci]不为0,那么同一件物品有可能重复叠加到同一容量上(例如草稿纸费用为1时,容量1的背包先放入一个草稿纸,容量2的背包=容量1背包+草稿纸=草稿纸+草稿纸)
1.2、容量降序,F[k − 1, v − Ci]、F[k − 1, v]都是0,那么初始态所有容量的结果都是0,容量2=max(容量1,容量1+草稿纸)=容量1+草稿纸=草稿纸,容量1=容量0+草稿纸=草稿纸
样例:
依赖背包的原始数据:
20 4
1 3 0
4 5 0
8 2 1
14 5 1
分组以后的策略:
1:3 9:19 15:73 23:89
4:20
第一组放置
遍历第二组
分组挑选策略:
F_optimize = collections.defaultdict(int)
for groupIndex in range(len(strategy)):
for volume in range(n+1,0,-1):
for item in strategy[groupIndex]:
if (volume-item.price)<0:
continue
F_optimize[volume] = max(F_optimize[volume],F_optimize[volume-item.price]+item.satisfaction)
pass
pass
pass
print(F_optimize[n])