- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
深入分区间型动态规划
深入分析区间型动态规划
??????? 郑州市第九中学??? 张旭祥
? 区间型动态规划在信息学竞赛中应用甚广,它是动态规划中的经典问题,最小代价字母树是这类动态规划最经典的体现,对于初学者而言这类动态规划并不太好理解。于是,区间型动态规划又成了动态规划中的难点问题。下面,本文将为大家深入分析区间型动态规划的思想及其程序的实现,希望能对大家有所帮助。
历届大赛中区间型动态规划题目的考查。
区间型动态规划是各大信息竞赛出题的热点,具体体现在以下题目:
合并石子----NOI1995
能量项链---NOIP2006
加分二叉树----NOIP2003
最优排序二叉树---- CTSC96
这些题目出现的频次及其所在比赛的重要性足以说明区间型动态规划在各类动态规划中有着举足轻重的地位。
二、区间型动态规划的算法分析
在这里就以经典的最小代价字母树作为例子,对区间型动态规划的算法进行分析。
问题描述:
给定一个序列,如4、1、2、3我们将他们相加进行合并,最终合并成一个数,每次相加的代价是两个加数的和,求怎样的相加顺序可以使总代价最小。
很多初学者认为这类动态规划不易理解,其重要原因是这类动态规划与其他动态规划的思想不大相同,而初学者又是利用其他动态规划的思想来解决这类动态规划,从而进入了思维误区。这种错误的思维模式一旦建立便很难重新建立正确的解题思想,从而陷入绝境。
这类动态规划正确的解法是这样的:
首先,根据动态规划无后效性的性质可以想到:对于一个序列:A1、A2……An,假如最后相加的两个数是第一个数到第i个数的和S[1--i]以及第i+1个数到第n个数的和S[i+1--n],另外,对于第一个数到第i个数相加的最小代价是F[1,i]以及从第i+1到第n个数相加的最小代价为F[i+1,n],则总代价即为F[i+1,n]+F[1,i](前面相加的最小代价)+ S[1--i]+ S[i+1--n](最后一次相加的最小代价)。由此,我们可以清楚的看出要想求出总代价的最小值只要枚举i的位置,使得F[i+1,n]+F[1,i] + S[1--i]+ S[i+1--n]的和最小即可。综上所述我们可以总结出状态转移方程:
F[I,J]:=min{F[I,k]+F[k+1,j]+S[I,k]+S[k+1,j]}
状态转移数组F即代表从第i个数到第j个数相加的最小代价,S数组为预处理好的从第i个数到第j个数的和。
核心代码如下:
For i:=1 to n do
For j:=1 to n-I do
For k:=j to i+j-1 do
? If F[j,i+j]F[j,k]+F[k+1,i+j]+S[j,k]+S[k+1,i+j]
?? then F[j,i+j]:=F[j,k]+F[k+1,i+j]+S[j,k]+S[k+1,i+j];
最小值ANS为F[1,n].
二、区间型动态规划的具体应用
1、石子归并
题目描述:
在一个圆形操场的四周摆放着N堆石子(N= 100),现要将石子有次序地合并成一堆.规定每次只能选取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.编一程序,由文件读入堆栈数N及每堆栈的石子数(=20).
(1)选择一种合并石子的方案,使用权得做N-1次合并,得分的总和最小;
(2)选择一种合并石子的方案,使用权得做N-1次合并,得分的总和最大;
输入数据:
第一行为石子堆数N;
第二行为每堆的石子数,每两个数之间用一个空格分隔.
输出数据:
从第一至第N行为得分最小的合并方案.第N+1行是空行.从第N+2行到第2N+1行是得分最大合并方案.每种合并方案用N行表示,其中第i行(1=i=N)表示第i次合并前各堆的石子数(依顺时针次序输出,哪一堆先输出均可).要求将待合并的两堆石子数以相应的负数表示.
输入输出范例:
输入:
4
4 5 9 4
输出:
-4 5 9 -4
-8 -5 9
-13 -9
22
4 -5 -9 4
4 -14 -4
-4 -18
22
这道题目可以说跟最小代价字母树只有两个不同的地方,一个是所求序列是一个环形的,另一个是要求输出方案,对于输出方案而言,只需要用一般动态规划记录方案的方法即可,因为不是本文的重点在此就不再深究。对于所求序列是环形的问题其实只需要用一个小小的技巧便轻松解决,请先看代码:
{------------------预处理------------------}
Read(n);
For? i:=1 to n do
Begin
? Read(a[i]);
? a[i+n]:=a[i];
End;
For i:=1 to n do
For j:=1 to n do
? For k:=i to j do
??? S[I,j]:=S[I,j]+a[
文档评论(0)