算法题总结-分组背包

原题
有 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])
posted @ 2023-06-11 16:15  356a  阅读(19)  评论(0编辑  收藏  举报