动态规划经典教程Word格式.doc

上传人:b****1 文档编号:13165187 上传时间:2022-10-07 格式:DOC 页数:46 大小:344KB
下载 相关 举报
动态规划经典教程Word格式.doc_第1页
第1页 / 共46页
动态规划经典教程Word格式.doc_第2页
第2页 / 共46页
动态规划经典教程Word格式.doc_第3页
第3页 / 共46页
动态规划经典教程Word格式.doc_第4页
第4页 / 共46页
动态规划经典教程Word格式.doc_第5页
第5页 / 共46页
点击查看更多>>
下载资源
资源描述

动态规划经典教程Word格式.doc

《动态规划经典教程Word格式.doc》由会员分享,可在线阅读,更多相关《动态规划经典教程Word格式.doc(46页珍藏版)》请在冰豆网上搜索。

动态规划经典教程Word格式.doc

动态规划用于解决多阶段决策最优化问题,但是不是所有的最优化问题都可以用动态规划解答呢?

一般在题目中出现求最优解的问题就要考虑动态规划了,但是否可以用还要满足两个条件:

最优子结构(最优化原理)

无后效性

最优化原理在下面的最短路径问题中有详细的解答;

什么是无后效性呢?

就是说在状态i求解时用到状态j而状态j就解有用到状态k…..状态N。

而求状态N时有用到了状态i这样求解状态的过程形成了环就没法用动态规划解答了,这也是上面用图论理解动态规划中形成的图无环的原因。

也就是说当前状态是前面状态的完美总结,现在与过去无关。

当然,有是换一个划分状态或阶段的方法就满足无后效性了,这样的问题仍然可以用动态规划解。

三,动态规划解决问题的一般思路。

拿到多阶段决策最优化问题后,第一步要判断这个问题是否可以用动态规划解决,如果不能就要考虑搜索或贪心了。

当却定问题可以用动态规划后,就要用下面介绍的方法解决问题了:

(1)模型匹配法:

最先考虑的就是这个方法了。

挖掘问题的本质,如果发现问题是自己熟悉的某个基本的模型,就直接套用,但要小心其中的一些小的变动,现在考题办都是基本模型的变形套用时要小心条件,三思而后行。

这些基本模型在先面的分类中将一一介绍。

(2)三要素法

仔细分析问题尝试着确定动态规划的三要素,不同问题的却定方向不同:

先确定阶段的问题:

数塔问题,和走路问题(详见解题报告)

先确定状态的问题:

大多数都是先确定状态的。

先确定决策的问题:

背包问题。

(详见解题报告)

一般都是先从比较明显的地方入手,至于怎么知道哪个明显就是经验问题了,多做题就会发现。

(3)寻找规律法:

这个方法很简单,耐心推几组数据后,看他们的规律,总结规律间的共性,有点贪心的意思。

(4)边界条件法

找到问题的边界条件,然后考虑边界条件与它的领接状态之间的关系。

这个方法也很起效。

(5)放宽约束和增加约束

这个思想是在陈启锋的论文里看到的,具体内容就是给问题增加一些条件或删除一些条件使问题变的清晰。

第二节动态规划分类讨论

这里用状态维数对动态规划进行了分类:

1.状态是一维的

1.1下降/非降子序列问题:

问题描述:

 

{挖掘题目的本质,一但抽象成这样的描述就可以用这个方法解}

在一个无序的序列a1,a2,a3,a4…an里,找到一个最长的序列满足:

ai<

=aj<

=ak…<

=am,且i<

j<

k…<

m.(最长非降子序列)或ai>

aj>

ak…>

am,且i>

j>

k…>

m.(最长下降子序列)。

问题分析:

如果前i-1个数中用到ak(ak>

ai或ak<

=ai)构成了一个的最长的序列加上第I个数ai就是前i个数中用到i的最长的序列了。

那么求用到ak构成的最长的序列有要求前k-1个数中……

从上面的分析可以看出这样划分问题满足最优子结构,那满足无后效性么?

显然对于第i个数时只考虑前i-1个数,显然满足无后效性,可以用动态规划解。

分析到这里动态规划的三要素就不难得出了:

如果按照序列编号划分阶段,设计一个状态opt[i]表示前i个数中用到第i个数所构成的最优解。

那么决策就是在前i-1个状态中找到最大的opt[j]使得aj>

ai(或aj<

=ai),opt[j]+1就是opt[i]的值;

用方程表示为:

{我习惯了这种写法,但不是状态转移方程的标准写法}

opt[i]=max(opt[j])+1 

(0<

=j<

i且aj<

=ai) 

{最长非降子序列}

i且aj>

ai) 

{最长下降子序列}

实现求解的部分代码:

opt[0]:

=maxsize;

{maxsize为maxlongint或-maxlongint}

for 

i:

=1tondo

forj:

=0toi-1do

if(a[j]>

a[i])and(opt[j]+1>

opt[i])then

opt[i]:

=opt[j]+1;

ans:

=-maxlongint;

fori:

ifopt[i]>

ansthenans:

=opt[i];

{ans为最终解}

复杂度:

从上面的实现不难看出时间复杂度为O(N2),空间复杂度O(N);

例题1拦截导弹(missile.pas/c/cpp)来源:

NOIP1999(提高组)第一题

【问题描述】

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。

但是这种导弹拦截系统有一个缺陷:

虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。

某天,雷达捕捉到敌国的导弹来袭。

由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

【输入文件】missile.in

单独一行列出导弹依次飞来的高度。

【输出文件】missile.out

两行,分别是最多能拦截的导弹数,要拦截所有导弹最少要配备的系统数

【输入样例】

38920715530029917015865

【输出样例】

6

2

【问题分析】

有经验的选手不难看出这是一个求最长非升子序列问题,显然标准算法是动态规划。

以导弹依次飞来的顺序为阶段,设计状态opt[i]表示前i个导弹中拦截了导弹i可以拦截最多能拦截到的导弹的个数。

状态转移方程:

(h[i]>

=h[j],0=<

i) 

{h[i]存,第i个导弹的高度}

最大的opt[i]就是最终的解。

这只解决了第一问,对于第二问最直观的方法就是求完一次opt[i]后把刚才要打的导弹去掉,在求一次opt[i]直到打完所有的导弹,但这样做就错了。

不难举出反例:

61732

错解:

632/1/7 

正解:

61/732

其实认真分析一下题就回发现:

每一个导弹最终的结果都是要被打的,如果它后面有一个比它高的导弹,那打它的这个装置无论如何也不能打那个导弹了,经过这么一分析,这个问题便抽象成在已知序列里找最长上升序列的问题。

求最长上升序列和上面说的求最长非升序列是一样的,这里就不多说了。

时间复杂度为O(N2),空间复杂度为O(N)。

【源代码】

programmissile;

const

fin='

missile.in'

;

fout='

missile.out'

maxn=10000;

var

a,opt:

array[0..maxn]oflongint;

n,anslen,anstime:

longint;

procedure 

init;

x:

begin

assign(input,fin);

reset(input);

assign(output,fout);

rewrite(output);

n:

=0;

repeat

inc(n);

read(a[n]);

untilseekeof;

end;

proceduremain;

i,j:

fillchar(opt,sizeof(opt),0);

a[0]:

=maxlongint;

=i-1downto0do

if(a[j]>

=a[i])and(opt[j]+1>

anslen:

anslenthen

if(a[j]<

anstime:

anstimethen

procedureprint;

writeln(anslen);

writeln(anstime);

close(input);

close(output);

main;

print;

end.

例题二合唱队形(chorus.pas/c/cpp)来源:

NOIP2004(提高组)第一题

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。

合唱队形是指这样的一种队形:

设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 

则他们的身高满足T1<

...<

Ti>

Ti+1>

…>

TK(1<

=i<

=K)。

你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

【输入文件】

输入文件chorus.in的第一行是一个整数N(2<

=N<

=100),表示同学的总数。

第一行有n个整数,用空格分隔,第i个整数Ti(130<

=Ti<

=230)是第i位同学的身高(厘米)。

【输出文件】

输出文件chorus.out包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

【样例输入】

8

186186150200160130197220

【样例输出】

4

【数据规模】

对于50%的数据,保证有n<

=20;

对于全部的数据,保证有n<

=100。

出列人数最少,也就是说留的人最多,也就是序列最长。

这样分析就是典型的最长下降子序列问题。

只要枚举每一个人站中间时可以的到的最优解。

显然它就等于,包括他

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1