动态规划初步.docx

上传人:b****3 文档编号:26512932 上传时间:2023-06-20 格式:DOCX 页数:14 大小:28.82KB
下载 相关 举报
动态规划初步.docx_第1页
第1页 / 共14页
动态规划初步.docx_第2页
第2页 / 共14页
动态规划初步.docx_第3页
第3页 / 共14页
动态规划初步.docx_第4页
第4页 / 共14页
动态规划初步.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

动态规划初步.docx

《动态规划初步.docx》由会员分享,可在线阅读,更多相关《动态规划初步.docx(14页珍藏版)》请在冰豆网上搜索。

动态规划初步.docx

动态规划初步

动态规划初步

 

 

————————————————————————————————作者:

————————————————————————————————日期:

 

第八讲动态规划初步

一、动态规划简介

动态规划是运筹学的一个分支。

它是解决多阶段决策过程最优化问题的一种方法。

1951年,美国数学家贝尔曼(R.Bellman)提出了解决这类问题的“最优化原则”,1957年发表了他的名著《动态规划》,该书是动态规划方面的第一本著作。

动态规划问世以来,在工农业生产、经济、军事、工程技术等许多方面都得到了广泛的应用,取得了显著的效果。

 动态规划运用于信息学竞赛是在90年代初期,它以独特的优点获得了出题者的青睐。

此后,它就成为了信息学竞赛中必不可少的一个重要方法,几乎在所有的国内和国际信息学竞赛中,都至少有一道动态规划的题目。

所以,掌握好动态规划,是非常重要的。

动态规划是一种方法,是考虑问题的一种途径,而不是一种算法。

因此,它不像深度优先和广度优先那样可以提供一套模式。

它必须对具体问题进行具体分析。

需要丰富的想象力和创造力去建立模型求解。

[例8-1]拦截导弹

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

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

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

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

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

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

样例:

INPUT        OUTPUT

389207 155300299  170 15865 6(最多能拦截的导弹数)

ﻩﻩﻩﻩ   2(要拦截所有导弹最少要配备的系统数)

[问题分析]

第一部分是要求输入数据串中的一个最长不上升序列的长度,可使用递推的方法,具体做法是从序列的第一个元素开始,依次求出以第i个元素为最后一个元素时的最长不上升序列的长度len(i),递推公式为len

(1)=1,len(i)=max(len(j)+1),其中i>1,j=1,2,…i-1,且j同时要满足条件:

序列中第j个元素大于等于第i个元素。

第二部分比较有意思。

由于它紧接着第一问,所以很容易受前面的影响,采取多次求最长不上升序列的办法,然后得出总次数,其实这是不对的。

要举反例并不难,比如长为7的高度序列“754163 2”,最长不上升序列为“75432”,用多次求最长不上升序列的结果为3套系统;但其实只要2套,分别击落“7541”与“63 2”。

那么,正确的做法又是什么呢?

我们的目标是用最少的系统击落所有导弹,至于系统之间怎么分配导弹数目则无关紧要;上面错误的想法正是承袭了“一套系统尽量多拦截导弹”的思维定势,忽视了最优解中各个系统拦截数较为平均的情况,本质上是一种贪心算法。

如果从每套系统拦截的导弹方面来想行不通的话,我们就应该换一个思路,从拦截某个导弹所选的系统入手。

题目告诉我们,已有系统目前的瞄准高度必须不低于来犯导弹高度,所以,当已有的系统均无法拦截该导弹时,就不得不启用新系统。

如果已有系统中有一个能拦截该导弹,我们是应该继续使用它,还是另起炉灶呢?

事实是:

无论用哪套系统,只要拦截了这枚导弹,那么系统的瞄准高度就等于导弹高度,这一点对旧的或新的系统都适用。

而新系统能拦截的导弹高度最高,即新系统的性能优于任意一套已使用的系统。

既然如此,我们当然应该选择已有的系统。

如果已有系统中有多个可以拦截该导弹,究竟选哪一个呢?

当前瞄准高度较高的系统的“潜力”较大,而瞄准高度较低的系统则不同,它能打下的导弹别的系统也能打下,它够不到的导弹却未必是别的系统所够不到的。

所以,当有多个系统供选择时,要选瞄准高度最低的使用,当然瞄准高度同时也要大于等于来犯导弹高度。

解题时,用一个数组记下已有系统的当前瞄准高度,数据个数就是系统数目。

[程序清单]

constmax=1000;

vari,j,current,maxlong,minheight,select,tail,total:

longint;

height,longest,sys:

array [1..max]oflongint;

 line:

string;

begin

 write('Inputtestdata:

');

 readln(line);

 i:

=1;

 whilei<=length(line) do

  begin

  while(i<=length(line)) and(line[i]='')doi:

=i+1;

      current:

=0;

   while(i<=length(line)) and(line[i]<>'')do

  begin

  current:

=current*10+ord(line[i])-ord('0');

      i:

=i+1

    end;

   total:

=total+1;

     height[total]:

=current

 end;

  longest[1]:

=1;

 fori:

=2tototaldo

begin

 maxlong:

=1;

     forj:

=1 toi-1do

  begin

    ifheight[i]<=height[j]

     theniflongest[j]+1>maxlong

           thenmaxlong:

=longest[j]+1;

 longest[i]:

=maxlong

   end;

  end;

maxlong:

=longest[1];

fori:

=2tototaldo

    iflongest[i]>maxlongthenmaxlong:

=longest[i];

writeln(maxlong);

 sys[1]:

=height[1]; tail:

=1;

fori:

=2 tototaldo

  begin

  minheight:

=maxint;

 forj:

=1 to taildo

  if sys[j]>height[i]then

ifsys[j]

    beginminheight:

=sys[j];select:

=jend;

ifminheight=maxint

    thenbegin tail:

=tail+1;sys[tail]:

=height[i]end

  elsesys[select]:

=height[i]

end;

   writeln(tail)

end.

二、动态规划的几个基本概念

想要掌握好动态规划,首先要明白几个概念:

阶段、状态、决策、策略、指标函数。

1.阶段:

把所给问题的过程,恰当地分为若干个相互联系的阶段,以便能按一定的次序去求解。

描述阶段的变量称为阶段变量。

2.状态:

状态表示每个阶段开始所处的自然状况和客观条件,它描述了研究问题过程中的状况,又称不可控因素。

3.决策:

决策表示当过程处于某一阶段的某个状态时,可以作出不同的决定(或选择),从而确定下一阶段的状态,这种决定称为决策,在最优控制中也称为控制。

描述决策的变量,称为决策变量。

4.策略:

由所有阶段的决策组成的决策函数序列称为全过程策略,简称策略。

5.状态转移方程:

状态转移方程是确定过程由一个状态到另一个状态的演变过程。

6.指标函数:

用来衡量所实现过程优劣的一种数量指标,称为指标函数。

指标函数的最优值,称为最优值函数。

三、确定动态规划的思路

1、采用动态规划来解决问题,必须符合两个重要的条件。

(1)“过去的历史只能通过当前状态去影响它未来的发展,当前的状态是对以往历史的一个总结”,这种特性称为无后效性,是多阶段决策最优化问题的特征。

(2)作为整个过程的最优策略具有这样的性质:

即无论过去的状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。

简言之,一个最优策略的子策略总是最优的。

这就是最优化原理。

2、如果碰到一个问题,能够满足以上两个条件的话,那么就可以去进一步考虑如何去设计使用动态规划:

(1)划分阶段。

把一个问题划分成为许多阶段来思考

(2)设计合适的状态变量(用以递推的角度)

(3)建立状态转移方程(递推公式)

(4)寻找边界条件(已知的起始条件)

如果以上几个步骤都成功完成的话,我们就可以进行编程了。

四、动态规划解题的一些技巧

ﻩ由于动态规划并没有一个定式,这就需要去开拓我们创造力去构造并且使用它。

以下,通过一些具体的竞赛实例谈谈使用动态规划过程中的一些技巧。

[例8-2]堆塔问题,设有n个边长为1的正立方体,在一个宽为1的轨道上堆塔,但塔本身不能分离。

例如n=1时,只有1种方案□

    n=2时  有2种方案  

 堆塔的规则为底层必须有支撑,如下列的堆法是合法的.     

 下面的堆法是不合法的.

 

 程序要求:

输入n(n<=40),求出

 ①总共有多少种不同的方案

 ②堆成每层的方案数是多少,例如n=6时,堆成1层的方案数为1,……堆成6层的方案数为1……

[问题分析]问题①的分析见第七讲例7-3,关于问题②,可以这样考虑,将n个立方体的第一列去掉的话,则成为一个比n小的堆塔问题,这样问题②就可以用动态规划法来解。

具体方法是从1到n依次求出堆成每层的方案数,设f(n,k)为堆成k层的方案数,则递推公式为:

[算法设计] 由于n最大可达到40,所以堆塔的总方案数超过了长整形数的范围,程序采用了高精度加法运算。

[程序清单]

program ex8_2(input,output);

constmaxn=40;maxlen=maxndiv3;

typearraytype=array[0..maxlen]ofinteger;

var i,j,k,n,nn:

longint;

  total:

arraytype;

   f:

array[0..maxn,0..maxn] ofarraytype;

procedure add(vara:

arraytype;b:

arraytype);

vari:

longint;

begin

 for i:

=0 tomaxlendoa[i]:

=a[i]+b[i];

fori:

=0 to maxlen-1do

   ifa[i]>=10then

  begin

    a[i+1]:

=a[i+1]+1;

   a[i]:

=a[i]-10

 end

end;

procedureprint(a:

arraytype);

vari,j:

longint;

begin

i:

=maxlen;

 while (i>0)and(a[i]=0) do i:

=i-1;

  forj:

=idownto0dowrite(a[j])

end;

begin

   write('Input n:

');

 readln(n);

 fori:

=1tomaxlendototal[i]:

=0;

  total[0]:

=1;

 for i:

=1 ton-1doadd(total,total);

for i:

=1 tomaxn do

   forj:

=1 tomaxn do

     for k:

=0tomaxlen do f[i,j,k]:

=0;

  fori:

=1 tomaxndof[i,1,0]:

=1;

  fori:

=1to maxndof[i,i,0]:

=1;

  fornn:

=2to ndo

     fork:

=2to nn-1do

    begin

     fori:

=1to k-1doadd(f[nn,k],f[nn-i,k]);

   fori:

=1tok do

    ifnn-k>=ithenadd(f[nn,k],f[nn-k,i])

  end;

  write('Total=');

 print(total);

  writeln;

fork:

=1tondo

  begin

  write('Height=',k:

2,'Kind=':

10);

  print(f[n,k]);

  writeln;

 if kmod 23=0

then

   begin

  write('Press<Enter>tocontinue!

');

      readln

   end

end;

write('Presstocontinue!

');

  readln

end.

[例8-3]投资问题:

有n万元的资金,可投资于m个项目,其中m 和n为小于100的自然数。

对第i(1≤i≤m)个项目投资j万元(1≤j≤n,且 j为整数)可获得的回报为Q(i,j),请编程序,求解并输出最佳的投资方案(即获得回报总值最高的投资方案)。

输入数据放在一个文本文件中,格式如下:

m  n

Q(1 ,0)Q(1,1)······Q(1 ,n)

Q(2 , 0)Q(2 ,1)······Q(2 , n)

············

Q(m,0)Q(m,1)······Q(m,n)

输出数据格式为:

r

(1)r

(2)······r(m)P

其中r(i)(1≤i≤m)表示对第i个项目的投资万元数,P为总的投资回报值,保留两位有效数字,任意两个数之间空一格。

当存在多个并列的最佳投资方案时,只要求输出其中之一即可。

如输入数据如下时:

2 3

01.11.3 1.9

02.12.5 2.6

屏幕应输出:

123.6

[问题分析]本题可供考虑的递推角度只有资金和项目两个角度,从项目的角度出发,逐个项目地增加可以看出只要算出了对前k个项目投资j万元最大投资回报值(1≤j≤n),就能推出增加第k+1个项目后对前k+1个项目投资j万元最大投资回报值(1≤j≤n),设P[k,j]为前k个项目投资j万元最大投资回报值,则P[k+1,j]=Max(P[k,i]+Q[k+1,j-i]),0<=i<=j,k=1时,对第一个项目投资j万元最大投资回报值(0≤j≤n)是已知的(边界条件)。

[算法设计]动态规划的时间复杂度相对于搜索算法是大大降低了,却使空间消耗增加了很多。

所以在设计动态规划的时候,需要尽可能节省空间的占用。

本题中如果用二维数组存储原始数据和最大投资回报值的话,将造成空间不够,事实上,从前面的问题分析可知:

在计算对前k+1个项目投资j万元最大投资回报值时,只要用到矩阵Q的第k+1行数据和对前k个项目投资j万元最大投资回报值,而与前面的数据无关,后者也只需有一个一维数组存储即可,程序中用一维数组Q存储当前项目的投资回报值,用一维数组maxreturn存储对当前项目之前的所有项目投资j万元最大投资回报值(0≤j≤n),用一维数组temp存储对到当前项目为止的所有项目投资j万元最大投资回报值(0≤j≤n)。

为了输出投资方案,程序中使用了一个二维数组invest,invest[k,j]记录了对前k个项目投资j万元获得最大投资回报时投资在第k个项目上的资金数。

[程序清单]

programex8_3(input,output);

constmaxm=100;maxn=100;

typearraytype=array [0..maxn]ofreal;

vari,j,k,m,n,rest:

integer;

 q,maxreturn,temp:

arraytype;

invest:

array[1..maxm,0..maxn]ofinteger;

 result:

array[1..maxm] of integer;

  fname:

string;

  f:

text;

begin

 write('Inputthenameofdatafile:

');

   readln(fname);

 assign(f,fname);

 reset(f);

  readln(f,m,n);

 forj:

=0 tondoread(f,q[j]);

 readln(f);

  fori:

=1 tom do

  forj:

=0tondoinvest[i,j]:

=0;

 maxreturn:

=q;

 forj:

=0tondoinvest[1,j]:

=j;

 fork:

=2to m do

 begin

 temp:

=maxreturn;

    for j:

=0tondoinvest[k,j]:

=0;

 forj:

=0to ndoread(f,q[j]);

 readln(f);

   forj:

=0to ndo

     fori:

=0toj do

     if maxreturn[j-i]+q[i]>temp[j] then

      begin

      temp[j]:

=maxreturn[j-i]+q[i];

      invest[k,j]:

=i

     end;

   maxreturn:

=temp

  end;

 close(f);

  rest:

=n;

  fori:

=mdownto1do

begin

    result[i]:

=invest[i,rest];

  rest:

=rest-result[i]

end;

  for i:

=1tom do write(result[i],' ');

 writeln(maxreturn[n]:

0:

2)

end.

[例8-4] 花店橱窗布置问题(FLOWER)

(1)问题描述

 假设你想以最美观的方式布置花店的橱窗。

现在你有F束不同品种的花束,同时你也有至少同样数量的花瓶被按顺序摆成一行。

这些花瓶的位置固定于架子上,并从1至V顺序编号,V是花瓶的数目,从左至右排列,则最左边的是花瓶1,最右边的是花瓶V。

花束可以移动,并且每束花用1至F间的整数唯一标识。

标识花束的整数决定了花束在花瓶中的顺序,如果I<J,则令花束I必须放在花束J左边的花瓶中。

 例如,假设一束杜鹃花的标识数为1,一束秋海棠的标识数为2,一束康乃馨的标识数为3,所有的花束在放入花瓶时必须保持其标识数的顺序,即:

杜鹃花必须放在秋海棠左边的花瓶中,秋海棠必须放在康乃馨左边的花瓶中。

如果花瓶的数目大于花束的数目。

则多余的花瓶必须空置,且每个花瓶中只能放一束花。

 每一个花瓶都具有各自的特点。

因此,当各个花瓶中放入不同的花束时,会产生不同的美学效果,并以美学值(一个整数)来表示,空置花瓶的美学值为零。

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

当前位置:首页 > PPT模板 > 其它模板

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

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