数学建模之动态规划

  • 动态规划

    算法介绍

1、动态规划是运筹学的一个分支,是求解多阶段决策过程最优化问题的数学方法。

2、各个阶段决策的选取不是任意确定的,它依赖于当前面临的状态,又影响以后的发展。当各个阶段的决策确定后,就组成了一个决 策序列,因而也就决定了整个过程的一条活动路线,这样的一个前后关联具有链状结构的多阶段过程就称为多阶段决策问题。

3、动态规划在车辆工程技术领域有着广泛的应用,如"两档变速器最优换挡规律""混合动力汽车最优能量管理策略""栅格地图最优 路径搜索"等。

    1. 算法思想

1、美国数学家Bellman等人在20世纪50年代初提出了著名的最优化原理,把多阶段决策问题转化为一系列单阶段最优化问题

2、对最佳路径(最佳决策过程) 所经过的各个阶段,其中每个阶段始点到全过程终点的路径,必定是该阶段始点到全过程终点的一切可能路径中的最佳路径(最优决策),这 就是Bellman提出的著名的最优化原理。

3、简而言之,一个最优策略的子策略必然也是最优的

    1. 算法定义

在求解问题中,对于每一步决策,列出各种可能的局部解再依据某种判定条件,舍弃那些肯定不能得到最优解的局部解,在每一步都经过筛选,以每一步都是最优解来保证全局是最优解。

  1. 算法适用条件:

1最优化原理:最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。一个问题满足最优化原理又 称其具有最优子结构性质。

2无后效性:将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它末来的决策,而只能影响当前的这个状态。换句话 说,每个状态都是过去历史的一个完整总结。

3子问题的重叠性动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储过程中产生的各种状态,所以它的空间复杂度要大于其他的算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间。

  1. 基本步骤

1、按照问题的特征,把问题分为若干个阶段。

2、将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。

3、确定决策并写出状态转换方程。

4、给出的状态转移方程是一个递推式,需要一个递推的终止条件和边界条件。

案例1:动态规划解决0-1背包问题

w

4

6

2

2

5

1

v

8

10

6

3

7

2

背包容量为12

算法一:
import numpy as np

def knapsack(w,v,C):
	mem=np.zeros((len(w)+1,C+1))
	for i in range(1,len(w)+1):
		for j in range(1,C+1):
			if w[i-1]<=j:
mem[i,j]=max(mem[i,j],mem[i-1,j],mem[i-1,j-w[i-1]]+v[i-1])
			else:
				mem[i,j]=mem[i-1][j]
	return mem[-1][-1]

if __name__ == "__main__":
    w = [4,6,2,2,5,1]
    v = [8,10,6,3,7,2]
    C = 12
print("最大价值为:{}".format(knapsack(w,v,C)))

结论:最大价值为24

算法二:
import numpy as np

#行李数n,不超过的重量W,重量列表w和价值列表p
def fun(n,W,w,p):
	a=np.array([[0]*(W+1)]*(n+1))
	#依次计算前i个行李的最大价值,n+1在n的基础上进行
	for i in range(1,n+1):
		for j in range(1,W+1):
			if w[i-1]>j:
				a[i,j]=a[i-1,j]
			else:
				a[i,j]=max(a[i-1,j],p[i-1]+a[i-1,j-w[i-1]])#2种情况取最大值
	#print(a)
	print('max value is:'+str(a[n,W]))
	findDetail(p,n,a[n,W])
#找到价值列表中的一个子集,使得其和等于前面求出的最大价值,即为选择方案
def findDetail(p,n,v):
	a=np.array([[True]*(v+1)]*(n+1))
	for i in range(0,n+1):
		a[i][0]=True
	for i in range(1,v+1):
		a[0][i]=False
	for i in range(1,n+1):
		for j in range(1,v+1):
			if p[i-1]>j:
				a[i,j]=a[i-1,j]
			else:
				a[i,j]=a[i-1,j] or a[i-1,j-p[i-1]]
	if a[n,v]:
		i=n
		result=[]
		while i>=0:
			if a[i,v] and not a[i-1,v]:
				result.append(p[i-1])
				v-=p[i-1]
			if v==0:
				break
			i-=1
		print(result)
	else:
		print('error')
weights=[4,6,2,2,5,1]
price=[8,10,6,3,7,2]
fun(len(weights),12,weights,price)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

王的傲骨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值