动态规划(Python)

一、动态规划

1、动态规划的定义

动态规划是将原始问题划分为若干个子问题,通过仅求解每个子问题一次,并将其结果保存在一个表结构中,以后用到的时候直接存取的方法。

2、适用于动态规划的问题

① 优化子结构

优化子结构,即一个问题的优化解包含了子问题的优化解。

② 重叠子问题

在问题求解过程中,很多子问题的解被多次使用。

3、动态规划算法步骤

① 分析优化解的结构

② 建立状态转移方程(递归方程)

③ 自底向上地求解各个子问题

一是计算优化解的代价并保存

二是获取构造最优解的信息并保存

④ 根据构造最优解的信息来构造优化解

二、动态规划求解0-1背包问题

给定n种物品和一个背包,物品i的重量是gif.latex?w_%7Bi%7D, 价值gif.latex?v_%7Bi%7D , 背包承重为C, 问如何选择装入背包的物品,使装入背包中的物品的总价值最大?

以下方算例为例,求解0-1背包问题。

物品重量价值
126
223
365
454
546

背包最大承重C为10。

1、基本模型

① 分析优化解结构

(1) gif.latex?max%20%5Csum_%7Bi%5Cleq%20k%5Cleq%20n%7Dv_%7Bk%7Dx_%7Bk%7D

(2)  gif.latex?%5Csum_%7Bi%5Cleq%20k%5Cleq%20n%7Dw_%7Bk%7Dx_%7Bk%7D%5Cleq%20j

(3) gif.latex?x_%7Bk%7D%3D%200%2C1%2C%20i%5Cleq%20k%5Cleq%20n

子问题v[i][j]表示只允许前i件物品放入容量为j的背包内可以获得的最大价值。

② 建立状态转移方程

(1) 第一种情况

若第i件物品重量gif.latex?w_%7Bi%7D大于背包最大承重j,那么该子问题转化为前i-1件物品放入容量j背包内可以获得的最大价值,即

v[i][j] = v[i-1][j]

(2) 第二种情况

若第i件物品重量gif.latex?w_%7Bi%7D小于等于背包最大承重j,那么该子问题转化为 前i-1件物品放入容量j背包内可以获得的最大价值 与 前i-1件物品放入容量为j-gif.latex?w_%7Bi%7D背包内可以获得的最大价值 的最大值,即

v[i][j] = max {v[i-1][j],v[i-1][j-gif.latex?w_%7Bi%7D]}

 ③ 自底向上地求解各个子问题

一是计算优化解的代价并保存

二是获取构造最优解的信息并保存

④ 根据构造最优解的信息来构造优化解

该问题最优解的值即为v[n][C]

2、代码求解

import numpy as np


# 求解0-1背包问题:n为物品数量;weight为背包最大承重;
# weight_list为物品重量表;value_list为物品价值表;
def bag(n, weight, weight_list, value_list):
    # value_mat保存最优解的代价
    value_mat = np.zeros((n + 1, weight + 1))
    # object_mat保存获取最优解的信息
    object_mat = [[] for i in range(n + 1)]
    # 自底向上地求解各个子问题
    for i in range(1, n + 1):
        for j in range(weight + 1):
            # 第一种情况
            if weight_list[i - 1] > j:
                value_mat[i][j] = value_mat[i - 1][j]
                object_mat[i].append(0)
            # 第二种情况
            else:
                if value_mat[i - 1][j] >= value_list[i - 1] + value_mat[i - 1][j - weight_list[i - 1]]:
                    value_mat[i][j] = value_mat[i - 1][j]
                    object_mat[i].append(0)
                else:
                    value_mat[i][j] = value_list[i - 1] + value_mat[i - 1][j - weight_list[i - 1]]
                    object_mat[i].append(i)
    # 求解该问题的最优解
    best_value = value_mat[n][weight]
    object_list = []
    x = n
    y = weight
    # 求解获取该问题最优解的信息
    while x > 0 and y > 0:
        if object_mat[x][y] != 0:
            object_list.append(object_mat[x][y])
            x -= 1
            y -= weight_list[x - 1]
        else:
            x -= 1
    object_list.reverse()
    # 返回最优解及其信息
    return best_value, object_list


# 求解该算例
value, objects = bag(5, 10, [2, 2, 6, 5, 4], [6, 3, 5, 4, 6])
print(value, objects)

3、输出结果

15.0 [1, 2, 5]

 

 

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学习啊ZzZ

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值