Select Language

AI社区

AI技术百科

2.17、Python解决0-1背包问题

背包问题是一个经典的问题,其有多个变种,本节要解决的是 0-1 背包问题。

题目如下,给定一个背包,其容量为 v,现在有 n 个物品,它们的体积分别为 e1、e2、…、en。现在挑选任意多个物品放入背包内,要求它们的体积和不能超过背包容量 v,并且希望尽量接近 v,如背包容量为 100,那么物品体积和为 99 的方案就比物品体积和为 98 的方案要好,当然最好是体积和等于背包容量 v。我们就是要找到这个最优的物品组合。

为了说明该类问题的解决方案,我们设定了一个特殊的场景,在该场景中,背包容量为 10,物品有 4 个,它们的容量分别为 1、3、6、8。现在我们需要计算出这个最优的物品组合。

最简单的方法就是列出所有的排列组合,看看它们是否满足条件。由于有 4 个物体,每个物体有两个可能选项,放入背包或者不放入背包。下面为实现代码:

goods_list = [1, 3, 6, 8]
def resolve_bag(bag_volume, goods_list):
    biggest_valid_vol = 0
    biggest_valid_selection = []
    goods_num = len(goods_list)
    candidate_num = 1 << goods_num
    for candidate in range(candidate_num):
        selection_decision = []
        for x in range(goods_num):
            if (candidate & 1) == 1:
                selection_decision.append(True)
            else:
                selection_decision.append(False)
            candidate = candidate >> 1
        current_vol = 0
        for x in range(goods_num):
            if selection_decision[x] == True:
                current_vol = current_vol + goods_list[x]
        if current_vol  biggest_valid_vol:
            biggest_valid_vol = current_vol
            biggest_valid_selection = selection_decision
    result = [goods_list[x] for x in range(goods_num) if biggest_valid_selection[x] == True]
    print(result)
resolve_bag(10, goods_list)

运行结果:
[1, 3, 6]

但是该程序的运行效率比较低下,其枚举了所有的组合。对于这个过程,可以用决策树来表示。

我们可以用两个信息来描述每个状态,一个是背包的剩余空间,一个是没有放入背包的物品。如初始状态就是有 10 个剩余空间,没有放入背包的物品体积依次为 1、3、6、8。然后我们对于所有的物品,从右往左,依次决定是否放入背包。如将体积为 8 的物品放入背包,那么就得到这样一个状态,其背包剩余空间是 2,没有放入到背包的物品容量是 1、3、6。如果决定不将体积为8的放入背包,那么就得到这样一个状态,剩余空间为 10,没有放入背包的物品体积为 1、3、6。

除掉一些明显不太可能出现的状态,可以得到如图1所示的一个状态图。

背包问题的状态图
图1:背包问题的状态图


最后找到右下角的这个状态,剩余空间为 0,即将背包完全装满了。这就是我们的终极状态了。


我要发帖
  • 26

    条内容
Python基本数据类型一共26个章节
本章将介绍 Python 内置的基本数据类型,包括整型、浮点数、字符串、布尔型、列表、元组、集合和字典等 Python 定义的基本数据类型,以及这些数据类型的运算操作。
我们知道,Python 是强类型语言,每个变量在某个时刻的类型是确定的。也就是说,Python 中任意一个存活的对象,其类型是唯一的。不同类型的对象有不同的属性,能完成不同的操作。
另外本章最后还会介绍变量、对象等概念。每个对象都有一个确定的类型,每个变量都指向某个特定的对象。