穷举法解决0-1背包问题

穷举法是将所有的候选解按某种顺序进行逐一枚举和检验,并从中找出符合要求的候选解作为问题的解,是一种暴力解法,算法思路简单,但复杂度高,一般用于数据量小的情况。

下面利用穷举法解决0-1背包问题:

[0-1背包问题] 有一个背包,背包容量是M=150kg。有7个物品,物品不可以分割成任意大小。
要求:尽可能让装入背包中的物品总价值最大,但不能超过总容量。

物品ABCDEFG
重量35kg30kg6kg50kg40kg10kg25kg
价值10403050354030

算法实现(Python 3):

import time

"""
穷举法:
暴力解法,算法思路简单,但复杂度高,一般用于数据量小的情况
"""

# 物品类
class Item(object):
    def __init__(self, n, v, w):
        self.name = n
        self.value = float(v)
        self.weight = float(w)

    def get_name(self):
        return self.name

    def get_value(self):
        return self.value

    def get_weigth(self):
        return self.weight

    def __str__(self):
        return '<' + self.name + ',' + str(self.value) + ',' + str(self.weight) + '>'

# 物品转化为二进制表示
def get_binary_rep(n, num_digital):
    result = ''
    while n > 0:
        result = str(n % 2) + result
        n = n // 2

    if len(result) > num_digital:
        raise ValueError("not enough digits")

    for i in range(num_digital - len(result)):
        result = '0' + result

    return result

# 物品装包的可能组合
def gen_power_set(L):
    power_set = []

    for i in range(2**len(L)):
        bin_str = get_binary_rep(i, len(L))
        sub_set = []
        for j in range(len(L)):
            if bin_str[j] == '1':
                sub_set.append(L[j])
        power_set.append(sub_set)

    return power_set

# 构造物品列表
def built_item():
    names = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    values = [35, 30, 6, 50, 40, 10, 25]
    weights = [10, 40, 30, 50, 35, 40, 30]
    Items = []
    for i in range(len(names)):
        Items.append(Item(names[i], values[i], weights[i]))
    return Items

# 选择最优装包组合
def choose_best(pset, get_value, get_weight, max_weight):
    best_value = 0
    best_set = None
    for items in pset:
        items_value = 0
        items_weight = 0
        for item in items:
            items_value += get_value(item)
            items_weight += get_weight(item)
        if items_weight <= max_weight and items_value > best_value:
            best_value = items_value
            best_set = items
    return best_set, best_value


if __name__ == '__main__' :
    start = time.perf_counter()
    items = built_item()
    pset = gen_power_set(items)
    taken, max_value = choose_best(pset, Item.get_value, Item.get_weigth, max_weight=150)
    print ('Total value of items taken = ', max_value)
    print ('the items of bag is: ')
    for item in taken:
        print(item)
    end = time.perf_counter()
    print("runing time is %f" % (end - start))

输出结果:

Total value of items taken =  155.0
the items of bag is: 
<A,35.0,10.0>
<B,30.0,40.0>
<D,50.0,50.0>
<E,40.0,35.0>
runing time is 0.001090
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值