0-1背包问题 回溯法 Python

问题

问题分析

回溯法不同于动态规划。使用回溯法的关键是生成解空间,该问题的解空间是一个子集树,以深度优先的方式向下搜索判断,对于不符合条件的,采用剪枝函数直接结束本条路的循环。以节省时间。

样例

N=3, C=50
编号重量价值
14550
22530
32530

在这里插入图片描述


解题

思路分析

根据层数开始搜索,从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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AYO_YO

老板大气!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值