问题
问题分析
回溯法不同于动态规划。使用回溯法的关键是生成解空间,该问题的解空间是一个子集树,以深度优先的方式向下搜索判断,对于不符合条件的,采用剪枝函数直接结束本条路的循环。以节省时间。
样例
N=3, C=50
| 编号 | 重量 | 价值 |
|---|---|---|
| 1 | 45 | 50 |
| 2 | 25 | 30 |
| 3 | 25 | 30 |

解题
思路分析
根据层数开始搜索,从0开始,例如本例,当层数到达4时,就可以判定循环到达叶节点了,当搜索至[1,1]时,已经撑爆背包了,所以就没必要继续循环生成子节点了。重新选择从[1,0]继续向下搜索。
当搜索到达底部时,如果此解重量小于背包容量,即判断此解是不是最优解。如果是,则保留此解。最终循环结束后输出。
代码实现(Python)
max_V, now_W, now_V, best_X, goods = 0, 0, 0, [], [] # 最大价值、当前重量、当前价值、最优解、商品列表
print('请输入物品数量、背包容积,空格隔开:')
n, c = map(int, input().split())
for i in range(n):
print(f'请输入第{i + 1}个物品的重量和价值,空格隔开:')
goods.append(list(map(int, input().split())))
x = [0 for i in range(n)] # 初始化当前解
def backtrack(i): # i是层数,n个物品,共有n+1层
global max_V, now_V, now_W, best_X, x # 引入全局变量
if i >= n: # 当层数超过物品总数量的时候
if max_V < now_V: # 当最大值小于当前价值时,更新最大值
max_V = now_V
best_X = x[:] # 同步更新最优解
else:
if now_W + goods[i][0] <= c: # 如果当前重量加上该层对应物品的重量,可以装在背包里
x[i] = 1 # 那么就装入这个物品(当前物品的状态为1)
now_W += goods[i][0] # 更新当前重量和价值
now_V += goods[i][1]
backtrack(i + 1) # 进入下一个节点(如果符合条件就到底了)
now_W -= goods[i][0] # 另一侧节点
now_V -= goods[i][1]
x[i] = 0 # 初始化物品状态
backtrack(i + 1) # 进入下一层
backtrack(0) # 从第0层开始搜索
print(f'最大价值为:{max_V}')
print(f'应装物品编号为:{[i + 1 for i in range(n) if best_X[i]]}')
测试
输入
请输入物品数量、背包容积,空格隔开:
3 50
请输入第1个物品的重量和价值,空格隔开:
45 50
请输入第2个物品的重量和价值,空格隔开:
25 30
请输入第3个物品的重量和价值,空格隔开:
25 30
输出
最大价值为:60
应装物品编号为:[2, 3]

2067

被折叠的 条评论
为什么被折叠?



