动态规划求解0-1背包问题(Python)

目录

基本介绍

问题描述

基本原理

解决过程

Python代码

动态规划

绘制图像


基本介绍

问题描述

       有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?

基本原理

       动态规划与分治法类似,都是把大问题拆分成小问题,通过寻找大问题与小问题的递推关系,解决一个个小问题,最终达到解决原问题的效果。但不同的是,分治法在子问题和子子问题等上被重复计算了很多次,而动态规划则具有记忆性,通过填写表把所有已经解决的子问题答案纪录下来,在新问题里需要用到的子问题可以直接提取,避免了重复计算,从而节约了时间,所以在问题满足最优性原理之后,用动态规划解决问题的核心就在于填表,表填写完毕,最优解也就找到。

解决过程

定义参数:Vi 表示第 i 个物品的价值,Wi 表示第 i 个物品的体积,
定义 V(i, j):当前背包容量 j,前 i 个物品最佳组合对应的价值,同时背包问题抽象化(X1,X2,…,Xn,其中 Xi 取0或1,表示第 i 个物品选或不选)。

1、建立模型,即求:max(V_{1}X_{1}+V_{2}X_{2}+...+V_{n}X_{n})

2、寻找约束条件:W_{1}X_{1}+W_{2}X_{2}+...+W_{n}X_{n}<C

3、寻找递推关系式,面对当前商品有两种可能性:

  • 包的容量比该商品体积小,装不下,此时的价值与前 i-1 个的价值是一样的,即 V(i, j) = V(i-1, j);
  • 还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即 V(i, j) = max{V(i-1, j),V(i-1, j-w(i)) + v(i)}。其中 V(i-1, j)表示不装,V(i-1, j-w(i)) + v(i) 表示装了第 i 个商品,背包容量减少 w(i),但价值增加了 v(i);

由此可以得出递推关系式:

V(i, j)=\left\{\begin{matrix} & V(i-1, j)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ j<w(i)\\ & max(V(i-1, j), V(i-1, j-w(i))+v(i)) \ \ \ else \end{matrix}\right.
4、填表,初始化边界条件,V(0, j) = V(i, 0) = 0;

5、表格填完,即可得到最优解。

Python代码

动态规划

N = 5
C = 10
w = [2, 2, 6, 5, 4]  # 自定义物品重量
v = [6, 3, 5, 4, 6]  # 自定义物品价值
f = [[0 for j in range(C+1)] for i in range(N+1)]
y = [0]
x = range(N*C+1)
for i in range(1, N+1):
    for j in range(1, C+1):
        if j < w[i-1]:
            f[i][j] = f[i-1][j]
        else:
            if f[i-1][j-w[i-1]] + v[i-1] > f[i-1][j]:
                f[i][j] = f[i-1][j-w[i-1]] + v[i-1]
            else:
                f[i][j] = f[i-1][j]
        y.append(f[i][j])

绘制图像

plt.plot(x, y, label="动态规划算法", color="red", linestyle="--", marker="s", markersize=4)
xlabel = [0]
for x in range(1, N*C+1):
    xlabel.append(x)
plt.xticks(xlabel)
plt.xlabel("迭代次数")
plt.ylabel("最大价值")
plt.title("0-1背包问题的算法分析图")
plt.legend()
# plt.savefig(Path(__file__).name[0:-3]+".pdf")
plt.show()

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值