没有合适的资源?快使用搜索试试~ 我知道了~
动态规划经典教程,适合初学,好东西拿来给大家分享
资源推荐
资源详情
资源评论
动态规划经典教程
引言:本人在做过一些题目后对 有些感想,就写了这个总结:
第一节动态规划基本概念
一,动态规划三要素:阶段,状态,决策。
他们的概念到处都是,我就不多说了,我只说说我对他们的理解:
如果把动态规划的求解过程看成一个工厂的生产线,阶段就是生产某个商品的不同的环节,状态就
是工件当前的形态,决策就是对工件的操作。显然不同阶段是对产品的一个前面各个状态的小结,有一
个个的小结构成了最终的整个生产线。每个状态间又有关联(下一个状态是由上一个状态做了某个决策
后产生的)。
下面举个例子:
要生产一批雪糕,在这个过程中要分好多环节:购买牛奶,对牛奶提纯处理,放入工厂加工,加工
后的商品要包装,包装后就去销售……,这样没个环节就可以看做是一个阶段;产品在不同的时候有不
同的状态,刚开始时只是白白的牛奶,进入生产后做成了各种造型,从冷冻库拿出来后就变成雪糕(由
液态变成固态)。每个形态就是一个状态,那从液态变成固态经过了冰冻这一操作,这个操作就是
一个决策。
一个状态经过一个决策变成了另外一个状态,这个过程就是状态转移,用来描述状态转移的方程就
是状态转移方程。
经过这个例子相信大家对动态规划有所了解了吧。
下面在说说我对动态规划的另外一个理解:
用图论知识理解动态规划:把动态规划中的状态抽象成一个点,在有直接关联的状态间连一条有向
边,状态转移的代价就是边上的权。这样就形成了一个有向无环图 网(为什么无环呢?往下看)。
对这个图进行拓扑排序,删除一个边后同时出现入度为 的状态在同一阶段。这样对图求最优路径就是
动态规划问题的求解。
二,动态规划的适用范围
动态规划用于解决多阶段决策最优化问题,但是不是所有的最优化问题都可以用动态规划解答呢?
一般在题目中出现求最优解的问题就要考虑动态规划了,但是否可以用还要满足两个条件:
最优子结构(最优化原理)
无后效性
最优化原理在下面的最短路径问题中有详细的解答;
什么是无后效性呢?
就是说在状态 求解时用到状态 而状态 就解有用到状态 …状态 。
而求状态 时有用到了状态 这样求解状态的过程形成了环就没法用动态规划解答了,这也是上面用
图论理解动态规划中形成的图无环的原因。
也就是说当前状态是前面状态的完美总结,现在与过去无关。。。
当然,有是换一个划分状态或阶段的方法就满足无后效性了,这样的问题仍然可以用动态规划解。
三,动态规划解决问题的一般思路。
拿到多阶段决策最优化问题后,第一步要判断这个问题是否可以用动态规划解决,如果不能就要考
虑搜索或贪心了。当却定问题可以用动态规划后,就要用下面介绍的方法解决问题了:
()模型匹配法:
最先考虑的就是这个方法了。挖掘问题的本质,如果发现问题是自己熟悉的某个基本的模型,就直
接套用,但要小心其中的一些小的变动,现在考题办都是基本模型的变形套用时要小心条件,三思而后
行。这些基本模型在先面的分类中将一一介绍。
()三要素法
仔细分析问题尝试着确定动态规划的三要素,不同问题的却定方向不同:
先确定阶段的问题:数塔问题,和走路问题(详见解题报告)
先确定状态的问题:大多数都是先确定状态的。
先确定决策的问题:背包问题。(详见解题报告)
一般都是先从比较明显的地方入手,至于怎么知道哪个明显就是经验问题了,多做题就会发现。
()寻找规律法:
这个方法很简单,耐心推几组数据后,看他们的规律,总结规律间的共性,有点贪心的意思。
()边界条件法
找到问题的边界条件,然后考虑边界条件与它的领接状态之间的关系。这个方法也很起效。
()放宽约束和增加约束
这个思想是在陈启锋的论文里看到的,具体内容就是给问题增加一些条件或删除一些条件使问题变
的清晰。
第二节动态规划分类讨论
这里用状态维数对动态规划进行了分类:
1.状态是一维的
1.1 下降/非降子序列问题:
问题描述:O挖掘题目的本质,一但抽象成这样的描述就可以用这个方法解
在一个无序的序列 … 里,找到一个最长的序列满足:…且 …
(最长非降子序列)或 …且 …(最长下降子序列)。
问题分析:
如果前 个数中用到 或 构成了一个的最长的序列加上第 个数 就是前 个数中用
到 的最长的序列了。那么求用到 构成的最长的序列有要求前 个数中……
从上面的分析可以看出这样划分问题满足最优子结构,那满足无后效性么?显然对于第 个数时只考
虑前 个数显然满足无后效性,可以用动态规划解。
分析到这里动态规划的三要素就不难得出了:如果按照序列编号划分阶段,设计一个状态 !"#$%表示
前 个数中用到第 个数所构成的最优解。那么决策就是在前 个状态中找到最大的 !"#$%使得 或
,!"#$%& 就是 !"#$%的值;用方程表示为:我习惯了这种写法,但不是状态转移方程的标准写法
!"#$%'!"#$%&((且 ((((((最长非降子序列
!"#$%'!"#$%&((且 (((((((最长下降子序列
实现求解的部分代码:
!"#$%)'*+,;'*+,为 '-!.# 或'-!.#
/!0()#!1!
/!0)#!1!
/$%$%1!"#$%&!"#$%#2,
!"#$%)!"#$%&3
*)'-!.#3
/!0)#!1!
/!"#$%*#2,*)!"#$%3(((((((((((((((*为最终解
复杂度:从上面的实现不难看出时间复杂度为 (),空间复杂度 ();
例题 1 拦截导弹OO(missile.pas/c/cpp) 来源:NOIP1999(提高组) 第一题
【问题描述】
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽
然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕
捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于 的正整数),计算这套系统最多能
拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
【输入文件】**-,
单独一行列出导弹依次飞来的高度。
【输出文件】**-,!4#
两行,分别是最多能拦截的导弹数,要拦截所有导弹最少要配备的系统数
【输入样例】
56766758
【输出样例】
8
【问题分析】
有经验的选手不难看出这是一个求最长非升子序列问题,显然标准算法是动态规划。
以导弹依次飞来的顺序为阶段,设计状态 !"#$%表示前 个导弹中拦截了导弹 可以拦截最多能拦截到
的导弹的个数。
状态转移方程:
!"#$%'!"#$%&(2$%2$%((2$%存,第 个导弹的高度
最大的 !"#$%就是最终的解。
这只解决了第一问,对于第二问最直观的方法就是求完一次 !"#$%后把刚才要打的导弹去掉,在求一
次 !"#$%直到打完所有的导弹,但这样做就错了。
不难举出反例:87
错解:8997((正解:897
其实认真分析一下题就回发现:每一个导弹最终的结果都是要被打的,如果它后面有一个比它高的
导弹,那打它的这个装置无论如何也不能打那个导弹了,经过这么一分析,这个问题便抽象成在已知序
列里找最长上升序列的问题。
求最长上升序列和上面说的求最长非升序列是一样的,这里就不多说了。
复杂度:时间复杂度为 (),空间复杂度为 ()。
【源代码】
"0!.0**-,3
:!*#
/;**-,;3
/!4#;**-,!4#;3
'3
<0
!"#)00=$'% !/
-!.#3
*-,*#,)-!.#3
"0!:,140,(#3
<0
')-!.#3
>,.
**."4#/3
0,*,#"4#3
**.!4#"4#/!4#3
0,?0#,!4#"4#3
)3
0,",#
:3
0,1$%3
4#-*,,,!/3
,13
"0!:,140,3
<0
)-!.#3
>,.
/--:20!"#*+,!/!"#3
$%)'-!.#3
/!0)#!1!
/!0)1!?#!1!
/ $%$% 1 !"#$%
&!"#$%#2,
!"#$%)!"#$%&3
*-,)3
/!0)#!1!
/!"#$%*-,#2,
*-,)!"#$%3
/--:20!"#*+,!/!"#3
$%)'-!.#3
/!0)#!1!
/!0)1!?#!1!
/ $%$% 1 !"#$%
&!"#$%#2,
!"#$%)!"#$%&3
*#,)3
/!0)#!1!
/!"#$%*#,#2,
*#,)!"#$%3
,13
"0!:,140,"0#3
>,.
?0#,-*-,3
?0#,-*#,3
:-!*,"4#3
:-!*,!4#"4#3
,13
>,.
#3
3
"0#3
,1
例题二OO合唱队形OO(chorus.pas/c/cpp) 来源: 提高组第一题
位同学站成一排,音乐老师要请其中的@位同学出列,使得剩下的 @ 位同学排成合唱队形。
合唱队形是指这样的一种队形:设 @ 位同学从左到右依次编号为 ,…,@,他们的身高分别为
A,A,…,A@,OO则他们的身高满足 AAA&…A@@。
你的任务是,已知所有 位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合
唱队形。
【输入文件】
输入文件 :2!04* 的第一行是一个整数 ,表示同学的总数。第一行有 个整数,用
空格分隔,第 个整数 AA是第 位同学的身高厘米。
【输出文件】
输出文件 :2!04*!4# 包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
【样例输入】
5
5858867
【样例输出】
【数据规模】
对于 %的数据,保证有 ;
对于全部的数据,保证有 。
【问题分析】
出列人数最少,也就是说留的人最多,也就是序列最长。
这样分析就是典型的最长下降子序列问题。只要枚举每一个人站中间时可以的到的最优解。显然它
就等于,包括他在内向左求最长上升子序列,向右求最长下降子序列。
我们看一下复杂度:
计算最长下降子序列的复杂度是 (),一共求 次,总复杂度是 ()。这样的复杂度对
于这个题的数据范围来说是可以 B 的。但有没有更好的方法呢?
其实最长子序列只要一次就可以了。因为最长下降(上升)子序列不受中间人的影响。
只要用 A 求一次最长上升子序列,A 求一次最长下降子序列。这样答案就是 '!"#$%
&!"#$%
复杂度由 ()降到了 ()。
【源代码】
"0!.0:2!04*3
:!*#
/;:2!04*;3
/!4#;:2!04*!4#;3
'3
<0
!"#!"#)00=$'%!/
-!.#3
*)-!.#3
"0!:,140,#3
<0
)-!.#3
>,.
**."4#/3
0,*,#"4#3
**.!4#"4#/!4#3
0,?0#,!4#"4#3
0,1-3
/!0)#!1!
0,1$%3
,13
"0!:,140,3
<0
)-!.#3
>,.
$%)'-!.#3
/!0)#!1!
/!0)1!?#!1!
/ $%$% 1 !"#$%
&!"#$%#2,
!"#$%)!"#$%&3
$&%)'-!.#3
/!0)1!?#!1!
/!0)&#!&1!
/ $%$% 1 !"#$%
&!"#$%#2,
!"#$%)!"#$%&3
*)3
/!0)#!1!
/!"#$%&!"#$%*#2,
*)!"#$%&!"#$%3
,13
"0!:,140,"0#3
>,.
?0#,-*&3
:-!*,"4#3
:-!*,!4#"4#3
,13
>,.
#3
3
"0#3
,1
例题 3 Buy Low Buy Lower (buylow.pas/c/cpp) 来源: USACO 4-3-1
【问题描述】
“逢低吸纳”是炒股的一条成功秘诀。如果你想成为一个成功的投资者,就要遵守这条秘诀)
C逢低吸纳越低越买C
这句话的意思是:每次你购买股票时的股价一定要比你上次购买时的股价低按照这个规则购买股票
的次数越多越好,看看你最多能按这个规则买几次。
给定连续的 天中每天的股价。你可以在任何一天购买一次股票,但是购买时的股价一定要比你上
次购买时的股价低。写一个程序,求出最多能买几次股票。
以下面这个表为例某几天的股价是)
天数(((((8(7(5(6(
股价858688587877586557
这个例子中聪明的投资者按上面的定义,如果每次买股票时的股价都比上一次买时低,那么他最
多能买 次股票。一种买法如下可能有其他的买法)
天数((8(
股价868588
【输入文件】>4=-!?
第 行)表示能买股票的天数。
第 行以下) 个正整数可能分多行,第 个正整数表示第 天的股价这些正整数大小不会超过
-!.#"*:-9-!.:&&
【输出文件】>4=-!?!4#
只有一行,输出两个整数:
能够买进股票的天数长度达到这个值的股票购买方案数量
在计算解的数量的时候,如果两个解所组成的字符串相同,那么这样的两个解被认为是相同的(只
能算做一个解)。因此,两个不同的购买方案可能产生同一个字符串,这样只能计算一次。
【输入样例】
85868858787
7586557
【输出样例】
【问题分析】
从题目描述就可以看出这是最长下降子序列问题,于是求解第一问不是难事,以天数为阶段,设计
状态 !"#$%表示前 天中要买第 天的股票所能得到的最大购买次数。
状态转移方程:
!"#$%'!"#$%&($%$%(($%存第 天股价
最大的 !"#$%就是最终的解。
第二问呢,稍麻烦一点。
从问题的边界出发考虑问题,当第一问求得一个最优解 !"#$%D 时,
剩余58页未读,继续阅读
资源评论
whx991201
- 粉丝: 0
- 资源: 3
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功