分枝定界法解0/1背包问题

分枝定界法解0/1背包问题

关键词:分支定界、0-1背包

分枝定界法简介

分枝定界法按照树形结构来组织解空间,展开节点后,有两种策略:

策略一、把节点加入 FIFO 队列当中;

策略二、把节点加入到堆中,按照最小消耗或者最大消耗来选择下一个展开节点

感悟

分枝定界法是一类能确保搜索到全部可行解的解空间的一类方法。得到全部的解以后,再由后续程序自行觉得。

分枝定界法与回溯法的区别

分枝定界法 回溯法
搜索解空间的方法是 BFS(广度优先) 搜索解空间的方法是 DFS(深度优先)
算法搜索的解空间大,消耗的内存多 算法搜索的解空间大,消耗的内存少

0/1背包问题

有背包问题形式化描述如下:

\[n = 3 \\ weights = [20, 15, 15] \\ values = [40, 25, 25] \\ constraint = 30 \]

用分枝定界法,代码实现如下:

# -*- coding:utf8 -*-
import copy
from collections import deque


# 用分枝定界法解决0/1背包问题
def brunch_bound(w, p, c):
    plan = list()
    buffer = deque([[copy.copy(w), [], []]])  # [waiting, explored, values]
    while len(buffer):
        cur = buffer.popleft()
        for i in range(0, len(cur[0])):
            weight = cur[0][i]
            n = copy.deepcopy(cur)
            n[0].remove(weight)
            n[1].append(weight)
            n[2].append(p[i])
            if sum(n[1]) > c:
                continue  # overloaded
            buffer.append(copy.deepcopy(n))
        plan.append(cur)
    return plan


if __name__ == '__main__':
    w = [20, 15, 15]
    p = [40, 25, 25]
    c = 30

    plan = brunch_bound(w,p,c)

    l = sorted(plan, key=lambda x:sum(x[2]), reverse=True)  # l[0] is the most value plan
    for e in l:
        print(e)

输出:

[[20], [15, 15], [25, 25]]  #显然,这是最优方案
[[20], [15, 15], [25, 25]]
[[15, 15], [20], [40]]
[[20, 15], [15], [25]]
[[20, 15], [15], [25]]
[[20, 15, 15], [], []]

解释

copy.copy 是浅拷贝,子对象不会被拷贝

copy.deepcopy 是深拷贝

posted @ 2018-09-08 16:26  健康平安快乐  阅读(940)  评论(2编辑  收藏  举报