大家好,我是连人。本期讲述回溯法中的最优装载问题。
以简单的语言说,就是给定两艘船,要求一批货物分别装入。
这道问题采用“先尽可能以最大载重装一艘船,再以剩下的货物装另一艘”。
这样,我们就将问题简化为了0-1背包问题。采用回溯法构建解空间,之后遍历即可。思路很简单,代码的注释我也写的很详细了。
def traceback(depth):
global n, goods, ship, best_arrange, now_arrange, best_load, now_load, remain
if depth >= n: # 遍历到叶节点,取较大值
if now_load > best_load:
best_arrange = now_arrange
best_load = now_load
return
remain -= goods[depth] # 将当前处理货物从剩余中扣去
if now_load + goods[depth] <= ship: # 如果加了这件货物没超最大载重
now_arrange[depth] = 1 # 那就将这件货物先记入当前解向量
now_load += goods[depth] # 并且将货物重量记为当前载重
traceback(depth+1) # 继续向下遍历
now_load -= goods[depth] # 遍历完之后将载重还原
if now_load + remain > best_load: # 如果不加上当前货物的重量还有可能在后方有大于最优装载的可能
now_arrange[depth] = 0 # 就不加入当前货物
traceback(depth+1) # 进行遍历 这个if中的思路不是"剪枝",而是多长了一个有可能的枝条
remain += goods[depth]
def result_out():
global best_arrange, best_load, ship, n, goods
l = 0
for i in range(0, n):
if best_arrange[i] == 0:
l += goods[i]
if l > ship:
print('无法装载')
else:
print('可以装载')
print('第一艘船装载:', end='')
for i in range(0, n):
if best_arrange[i] == 1:
print(i, end=' ')
print()
print('第二艘船装载:', end='')
for i in range(0, n):
if best_arrange[i] == 0:
print(i, end=' ')
if __name__ == '__main__':
n = 3 # 货物数量
goods = [40, 40, 10] # 货物
ship = 50 # 船的最大载重
best_arrange = [0, 0, 0] # 最优解向量
now_arrange = [0, 0, 0] # 遍历时当前解向量
best_load = 0 # 最优解时第一艘船的载重
now_load = 0 # 遍历时当前载重
remain = sum(goods) # 剩余货物重量
traceback(0)
result_out()
转载注明出处。