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

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

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

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

物品 A B C D E F G
重量 35kg 30kg 6kg 50kg 40kg 10kg 25kg
价值 10 40 30 50 35 40 30

算法实现(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: 
35.0,10.0>
30.0,40.0>
50.0,50.0>
40.0,35.0>
runing time is 0.001090

你可能感兴趣的:(数据结构与算法)