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