程序设计方法-动态规划法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

动态规划相关概念(续)
动态规划所依据的是“最优性原理”
“最优性原理”可陈述为:不论初始状态和第 一步决策是什么,余下的决策相对于前一次决 策所产生的新状态,构成一个最优决策序列。
最优决策序列的子序列,一定是局部最优 决策子序列。
包含有非局部最优的决策子序列,一定不 是最优决策序列。
动态规划相关概念(续)
动态规划的指导思想是:在做每一步决策时, 列出各种可能的局部解,之后依据某种判定条 件,舍弃那些肯定不能得到最优解的局部解。
在每一步都经过筛选,以每一步都是最优的来 保证全局是最优的。
筛选相当于最大限度地有效剪枝(从搜索角度 看),效率会十分高。
但它又不同于贪心法。贪心法只能做到局部最 优,不能保证全局最优,因为有些问题不符合 最优性原理。
决策:根据题意要求,对每个阶段所做出的 某种选择性操作。
状态转移方程:用数学公式描述与阶段相关 的状态间的演变规律。
动态规划相关概念
动态规划是运筹学的一个重要分支,是解 决多阶段决策过程最优化的一种方法
所谓多阶段决策过程,是将所研究的过程 划分为若干个相互联系的阶段,在求解时, 对每一个阶段都要做出决策,前一个决策 确定以后,常常会影响下一个阶段的决策。
(p( 0,6,3)|q=0) = 3 * p( 1,6,2 )
q=l+1=1 3 2 1 5 1 2 5 01234 5 6
d( l,q)=d(0,1)=32 p( q+1,r,k-1 )=p( 2,6,2 )
(p( 0,6,3)|q=1) = 32 * p( 2,6,2 )
q=l+2=2 3 2 1 5 1 2 5 01234 5 6
else return y;
}
//返回2个整数中的大者
参考程序(续)
int main() {
int peachtree[MAXLAYER][MAXLAYER]; int P[MAXLAYER][MAXLAYER]; int i, j, k, n;
//读入数据
cin >> n;
k = 1; //当前这层的节点数目
12 5 456
p(5,6,1) = 2 * 5 = 10
p(4,6,2) = 1 * p(5,6,1) = 10
p( 0,6,3)= max{ 3 * p( 1,6,2 ) , // q=0 32 * p( 2,6,2 ) , // q=1 321* p( 3,6,2 ) , // q=2 3215 * p( 4,6,2 ) } // q=3
( p( 0,6,3)|q=3) = 3215 * p( 4,6,2 )
p( 0,6,3)= max{ 3 * p( 1,6,2 ) , // q=0 32 * p( 2,6,2 ) , // q=1 321* p( 3,6,2 ) , // q=2 3215 * p( 4,6,2 ) } // q=3
例如:摘了有6个桃子的树枝之后只能摘有2个 4
6
5
桃子的树枝或是有3个桃子的树枝),然后继续
摘桃子。
小猴子现在想要从最低层开始一直爬到树顶(也就是最上 面的那个枝条),摘尽可能多的桃子。请你编程帮他解决 这个问题。
解题思路
题目似曾相识??
滑雪、迷宫…
可以用递归回溯方法解决
建议自写递归回溯的代码
参考程序如下
#include <stdio.h> #include <stdlib.h> #include <iostream>
using namespace std;
#define MAXLAYER 110
int maxnum(int x, int y) {
if (x > y) return x;
换一种思路
A:1
B:2
C:3
第2阶段 第1阶段
第0阶段
D:4
E:6
F:5
从最低一层爬到最顶点,经过的路径上数 字之和最大
思路
先看第2阶段,到达顶点有2条路
BA,可以摘到1个桃子,则经过B点到顶点最多 摘得桃子数是:到达B点手中最多的桃子数+1
CA,可以摘到1个桃子,则经过C点到顶点最多 摘得桃子数是:到达C点手中最多的桃子数+1
A1
P(D) = max{P(G), P(H)}+7 P(E) = max{P(H), P(I)}+6
B2 C9
P(F) = max{P(I), P(J)}+5
D7 E6 F 5
P(G) = 2, P(H) = 3, P(I) = 6, P(J) = 4
G2 H3 I 6 J4 x
将底层到每个点的最长路径P也存放在二维 数组中
p( 2,6,2 )
1* p(3,6,1 )
151 2 5 234 5 6
15 * p(4,6,1)
151 2 5 234 5 6
151 * p(5,6,1)
151 2 5 234 5 6
p( 2,6,2 )= { 1 * 2560, 15 * 60, 151 * 10 }
= 2560
p( 3,6,2 )
原问题转化为即求P[0][3]
P[x][ y] = max{P[x][ y-1], P[x+1][y-1]}+peachtree[x][y]
y > 0, x + y <= MAXLAYPER
注意边界条件,P[x][ 0] = peachtree[x][0]
y
1
29
765
2
3
6
4
x
最多能摘到22个桃子,路径如上图红色箭 头所示
5 * p(4,6,1 )
51 2 5 34 5 6
51 * p(5,6,1)
51 2 5 34 5 6
p( 3,6,2 ) = { 5 * 60 , 51 * 10 } = 510
p( 4,6,2 )
1*2*5
125 456
p( 4,6,2 ) = 10
p( 4,6,2 )
1* p(5,6,1 )
动态规划与贪心法区别
贪心法产生一个按贪心策略形成的判定序 列,该序列不保证解是全局最优的。
动态规划会产生许多判定序列,再按最优 性原理对这些序列加以筛选,去除那些非 局部最优的子序列。
举例说明动态规划思路
问题: 在数字串中插入若干乘号使 总的乘积最大
*
**
s
3215 1 2 5
0123 4 5 6
数组行上存放桃树上一层中每个树枝上桃子数
将节点上桃子数目存放在数组中
只使用数组中对角线及下部分
A:1
1 29
B:2
C:9
765
D:7
E:6
F:5
2364
G:2
H:3
I:6
J:4
问题分析
从二维数组最下面一行开始向
上一行沿图中的直线前进,走 到左上角的格子停止。
1
行走路径上经过的格子中的数 2 9 字之和是猴子爬到树顶能拿到
//递推过程P[x][y] = max{P[x][y-1], P[x+1][y-1]}+peachtree[x][y]
for (j = 1; j < n; j++)
// i是行号,j是列号
{
for (i = 0 ; i + j < n; i++)
{
P[i][j] = maxnum(P[i][j-1], P[i+1][j-1])+peachtree[i][j];
d( l,q)=d(0,2)=321 p( q+1,r,k-1 )=p( 3,6,2 )
(p( 0,6,3)|q=2) = 321 * p( 3,6,2 )
q=l+3=3 3 2 1 5 1 2 5 01234 5 6
d( l,q)=d(0,3)=3215 p( q+1,r,k1 )=p( 4,6,2 )
《程序设计实践》
程序设计方法之 动态规划
任务:摘桃子(1104)
长满桃子的树很大,共有n层(最
高层为第1层),第i层有i条树枝,
1
树的形状呈一个三角形(如图)
图中的点表示树枝,每个点上方的数字表示这条
树枝最多能摘到的桃子数
2
3
在摘得某枝条的桃子之后,小猴子只能选择往左 上方爬或者是往右上方爬
从上述两条路径中选择一条最优的

令P(X)表示从底层到X点可以摘到最多桃子数目, 包含X点可以摘到的桃子数目
则:P(A) = max{P(B),P(C)}+1
思路(续)
而第1阶段的
P(B) = max{P(D), P(E)}+2 P(C) = max{P(E), P(F)}+3 按照题意,P(D),P(E),P(F)分别初始化为4, 6, 5
}
}
cout << P[0][n-1] << endl;
return 0; }
动态规划
阶段 状态 决策 状态转移方程
动态规划的几个概念:
阶段:据空间顺序或时间顺序对问题的求解 划分阶段。
状态:描述事物的性质,不同事物有不同的 性质,因而用不同的状态来刻画。对问题 的求解状态的描述是分阶段的。
151 2 5 234 5 6
151 2 5 234 5 6
151 2 5 234 5 6
151 2 5 234 5 6
p(2,6,1) = max { 1 * 5125 , 15 * 125 , 151 * 25 , 1512 * 5 }
= 7560
p( 3,6,1 )
5 * 125
51 2 5 34 5 6
p( 1,6,2 )
2 * p(2,6,1 )
2151 2 5 1234 5 6
Байду номын сангаас
21 * p(3,6,1)
2151 2 5 1234 5 6
2151 2 5
215 * p(4,6,1)
1234 5 6
2151 2 5
2151 * p(5,6,1)
1234 5 6
p( 2,6,1 )
1* 5125 15 * 125 15 1* 25 1512 *5
上述递推公式说明,要求P(A)需要先求出 阶段1的P(B)和P(C),而要得到P(B)和P(C), 需要知道P(D),P(E),P(F)
思路(续)
显然,根据前面的递推过程求解,需要倒 过来,从P(D),P(E),P(F)出发,先求出第1阶 段的P(B)和P(C),最后得到P(A)。
数据结构
将长满桃子的树用二维数组保存
51 * 25
51 2 5 34 5 6
5 12* 5
51 2 5 34 5 6
p( 3,6,1 )=max{5*125, 51*25, 512*5 }
= 2560
p( 4,6,1 )
1 * 25
125 456
12 * 5
125 456
p( 4,6,1 ) = max { 1 * 25, 12 * 5 } = 60
p( q+1,r,k-1 )
d ( l , q )= s[l]s[l+1]…s[q]
p( l,r,k )=max{ d( l, q ) * p( q+1, r ,k-1 ) }
q=l,l+1,…,r-k
q=l=0
32151 2 5 01234 5 6
d( l,q)=d(0,0)=3 p( q+1,r,k-1 )=p( 1,6,2 )
p( 5,6,1 )
2*5
25 56
p(5,6,1) = 10
p( 1,6,2 )= max { 2 * p( 2,6,1 ) , 21 * p( 3,6,1) , 215 * p( 4,6,1) , 2151 * p( 5,6,1) }
=max{2*7560,21*2560,215*60,2151*10} = 53760
请插入3个乘号使乘积最大 32*15*12*5=28800 3*215*12*5=38700 321*51*2*5=163710
解题思路
定义 : 从 l 到 r 加入 k 个乘号的最大乘积

*
p( l , r , k )
l l+1 l+2 . . . q q+1 q+2 . . . r
d(l,q)
桃子的数目,我们定义为路径 7 6 5 长度。 原问题转化为求所有路径中路 2 3 6 4
径长度的最大值。
问题分析(续)
按照前面的思路,最长路径的长度是:
P(A) = max{P(B), P(C)}+1
y
P(B) = max{P(D), P(E)}+2
P(C) = max{P(E), P(F)}+9
for (i = 0; i < n; i++)
// n-i层的的节点
{
for (j = 0; j < k; j++)
{
cin >> peachtree[j][n-i-1];
}
k++;
}
参考程序(续)
//初始化P[x][0] for (i = 0; i < n; i++) {
P[i][0] = peachtree[i][0]; }
数据结构(续)
#define MAXLAYER 3 int peachtree[MAXLAYER][MAXLAYER] = {
{1, -1, -1, -1}, {2, 9, -1, -1}, {7, 6, 5, -1}, {2, 3, 6, 4} }; int P[MAXLAYER][MAXLAYER]
相关文档
最新文档