-
动态规划
算法介绍
1、动态规划是运筹学的一个分支,是求解多阶段决策过程最优化问题的数学方法。
2、各个阶段决策的选取不是任意确定的,它依赖于当前面临的状态,又影响以后的发展。当各个阶段的决策确定后,就组成了一个决 策序列,因而也就决定了整个过程的一条活动路线,这样的一个前后关联具有链状结构的多阶段过程就称为多阶段决策问题。
3、动态规划在车辆工程技术领域有着广泛的应用,如"两档变速器最优换挡规律"、"混合动力汽车最优能量管理策略"、"栅格地图最优 路径搜索"等。
-
-
算法思想
-
1、美国数学家Bellman等人在20世纪50年代初提出了著名的最优化原理,把多阶段决策问题转化为一系列单阶段最优化问题。
2、对最佳路径(最佳决策过程) 所经过的各个阶段,其中每个阶段始点到全过程终点的路径,必定是该阶段始点到全过程终点的一切可能路径中的最佳路径(最优决策),这 就是Bellman提出的著名的最优化原理。
3、简而言之,一个最优策略的子策略必然也是最优的。
-
-
算法定义
-
在求解问题中,对于每一步决策,列出各种可能的局部解再依据某种判定条件,舍弃那些肯定不能得到最优解的局部解,在每一步都经过筛选,以每一步都是最优解来保证全局是最优解。
-
算法适用条件:
1、最优化原理:最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。一个问题满足最优化原理又 称其具有最优子结构性质。
2、无后效性:将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它末来的决策,而只能影响当前的这个状态。换句话 说,每个状态都是过去历史的一个完整总结。
3、子问题的重叠性:动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储过程中产生的各种状态,所以它的空间复杂度要大于其他的算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间。
-
基本步骤
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)