ImageVerifierCode 换一换
格式:DOCX , 页数:18 ,大小:43.69KB ,
资源ID:7613518      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7613518.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(pascal教程8动态规划.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

pascal教程8动态规划.docx

1、pascal教程8动态规划第八章 动态规划8.1 字串距离 源程序名 blast.*(pas, c, cpp)可执行文件名 blast.exe输入文件名 blast.in输出文件名 blast.out【问题描述】 设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为”abcbcd”,则字符串“abcbcd”,“abcbcd”和“abcbcd”都是X的扩展串,这里“”代表空格字符。 如果A1是字符串A的扩展串,B1是字符串B的扩展串,A1与B1具有相同的长度,那么我扪定义字符串A1与B1的距离为相应位置上的字符的距离总和,而两个非空格字符的距离定义为它们

2、的ASCII码的差的绝对值,而空格字符与其他任意字符之间的距离为已知的定值K,空格字符与空格字符的距离为0。在字符串A、B的所有扩展串中,必定存在两个等长的扩展串A1、B1,使得A1与B1之间的距离达到最小,我们将这一距离定义为字符串A、B的距离。 请你写一个程序,求出字符串A、B的距离。【输入】 输入文件第一行为字符串A,第二行为字符串B。A、B均由小写字母组成且长度均不超过2000。第三行为一个整数K(1K100),表示空格与其他字符的距离。【输出】 输出文件仅一行包含一个整数,表示所求得字符串A、B的距离。【样例】 blast.in blast.out cmc 10 snmn 2【算法分

3、析】 字符串A和B的扩展串最大长度是A和B的长度之和。如字符串A为“abcbd”,字符串B为“bbcd”,它们的长度分别是la=5、lb=4,则它们的扩展串长度最大值为LA+LB=9,即A的扩展串的5个字符分别对应B的扩展串中的5个空格,相应B的扩展串的4个字符对应A的扩展串中的4个空格。例如下面是两个字符串的长度为9的扩展串: ab cbd bbcd 而A和B的最短扩展串长度为la与lb的较大者,下面是A和B的长度最短的扩展串: a b cbd bbcd 因此,两个字符串的等长扩展串的数量是非常大的,寻找最佳“匹配”(对应位置字符距离和最小)的任务十分繁重,用穷举法无法忍受,何况本题字符串长

4、度达到2000,巨大的数据规模,势必启发我们必须寻求更有效的方法:动态规划。 记为A串中A1到Ai的一个扩展串,为B串中B1到Bj的一个扩展串。这两个扩展串形成最佳匹配的条件是(1)长度一样;(2)对应位置字符距离之和最小。 首先分析扩展串与扩展串长度一样的构造方法。扩展串与扩展串可以从下列三种情况扩张成等长: (1)与为两个等长的扩展串,则在后加一空格,加字符Bj; (2)与为两个等长的扩展串,则在添加字符Ai,在后加一空格; (3)与为两个等长的扩展串,则在后添加字符Ai,在后添加字符Bj。 其次,如何使扩展成等长的这两个扩展串为最佳匹配,即对应位置字符距离之和最小,其前提是上述三种扩展方

5、法中,被扩展的三对等长的扩展串都应该是最佳匹配,以这三种扩展方法形成的等长扩展串(A1, A2, , Ai和也有三种不同情形,其中对应位置字符距离之和最小的是最佳匹配。 为了能量化上述的构造过程,引入记号gi, j为字符串A的子串A1, A2, , Ai与字符串B的子串B1, B2, , Bj的距离,也就是扩展串与扩展串是一个最佳匹配。则有下列状态转移方程: gi, j=Mingi-1, j+k, gi, j-1+k, gi-1, j-1+ 0iLa 0jLb 其中,k位字符与字符之间的距离;为字符ai与字符bi的距离。 初始值:g0, 0=0 g0, j=jk gi, 0=ik 综上所述,本

6、题的主要算法如下: (1)数据结构 var a, b:array1.2000of byte; 以ASCII码表示的字符串 g:array0.2000, 0.2000of longint; 各阶段的匹配距离 (2)读入字符串A、B,转换为ASCII码 la:=0; lb:=0; while not(eoln(f) do 子串长度单元 begin 从文件中读入一行字符 read(f, c); inc(la); ala:=ord(c); end; readln(f); while not(eoln(f) do begin read(f, c); inc(lb); blb:=ord(c); end;

7、readln(f); (3)根据状态转移方程求gla, lb g0, 0:=0; for i:=1 to la do gi, 0:=k+gi-1, 0; for j:=1 to lb do g0, j:=k+g0, j-1; for i:=1 to la do for j:=1 to lb do begin gi, j:=k+gi-1,j; temp:=gi, j-1+k; if gi, jtemp then gi, j:=temp; temp:=gi-1,j-1+abs(ai-bj); if gi, jtemp then gi, j:=temp; end; (4)输出 writeln(f,

8、gla, lb);8.2 血缘关系 源程序名 family.?(pas, c, cpp)可执行文件名 family.exe输入文件名 family.in输出文件名 family.out【问题描述】 我们正在研究妖怪家族的血缘关系。每个妖怪都有相同数量的基因,但是不同的妖怪的基因可能是不同的。我们希望知道任意给定的两个妖怪之间究竟有多少相同的基因。由于基因数量相当庞大,直接检测是行不通的。但是,我们知道妖怪家族的家谱,所以我们可以根据家谱来估算两个妖怪之间相同基因的数量。 妖怪之间的基因继承关系相当简单:如果妖怪C是妖怪A和B的孩子,则C的任意一个基因只能是继承A或B的基因,继承A或B的概率各占

9、50。所有基因可认为是相互独立的,每个基因的继承关系不受别的基因影响。 现在,我们来定义两个妖怪X和Y的基因相似程度。例如,有一个家族,这个家族中有两个毫无关系(没有相同基因)的妖怪A和B,及它们的孩子C和D。那么C和D相似程度是多少呢?因为C和D的基因都来自A和B,从概率来说,各占50。所以,依概率计算C和D平均有50的相同基因,C和D的基因相似程度为50。需要注意的是,如果A和B之间存在相同基因的话,C和D的基因相似程度就不再是50了。 你的任务是写一个程序,对于给定的家谱以及成对出现的妖怪,计算它们之间的基因相似程度。【输入】 第一行两个整数n和k。n(2n300)表示家族中成员数,它们

10、分别用1, 2, , n来表示。k(0kn-2)表示这个家族中有父母的妖怪数量(其他的妖怪没有父母,它们之间可以认为毫无关系,即没有任何相同基因)。 接下来的k行,每行三个整数a, b, c,表示妖怪a是妖怪b的孩子。 然后是一行一个整数m(1mn2),表示需要计算基因相似程度的妖怪对数。 接下来的m行,每行两个整数,表示需要计算基因相似程度的两个妖怪。 你可以认为这里给出的家谱总是合法的。具体来说就是,没有任何的妖怪会成为自己的祖先,并且你也不必担心会存在性别错乱问题。【输出】 共m行。可k行表示第k对妖怪之间的基因相似程度。你必须按百分比输出,有多少精度就输出多少,但不允许出现多余的0(注

11、意,0.001的情况应输出0.1%,而不是.1%)。具体格式参见样例。【样例】 family.in family.out 7 4 0% 4 1 2 50% 5 2 3 81.25% 6 4 5 100% 7 5 6 4 1 2 2 6 7 5 3 3【知识准备】 (1)基本的概率计算知识; (2)递推原理(包括记忆化搜索)。【算法分析】 本题是一道概率计算题,但这个概率计算又是建立在Family Tree模型上的。Family Tree是一个有向无环图,有明显的阶段性(辈分关系),而且没有后效性(没有人可以成为自己的祖先),符合动态规划模型的基本条件。因此,应该可以套用类似动态规划的方法来解决

12、。 我们先来明确一下相似程度的计算方法。假设我们要求的是A和B的相似程度(设为P(A, B)),那么有两种情况是显然的: (1)A=B:P(A, B)=1; (2)A与B无相同基因:P(A, B)=0。 这是计算其他复杂情况的基础。因为动态规划就是从一些特定的状态(边界条件)出发,分阶段推出其他状态的值的。 再来看一般的情况,设A0和A1是A的父母。那么,取概率平均情况,A拥有A0和A1的基因各占一半。假设A0与B的相似程度为P(A0, B),A1与B的相似程度为P(A1, B),那么P(A, B)与P(A0, B)和P(A1, B)之间应该是一个什么样的关系呢?很容易猜想到: P(A, B)

13、=(P(A0, B)+P(A1, B)/2 但是,这只是一个猜想。要让它变为一个结论还需要证明: 我们用归纳法来证明。 首先,我们知道,在这个问题中不同基因都是从特定的祖先传下来的,不会出现同一个基因采自不同的祖先的情况(注:这里的祖先是指那些没有父母的妖怪)。所以,如果A与B有相同的基因,这些基因必然来自同一个祖先。这里,我们最想说明的是,祖先那代是不存在两个人,它们之间不同的基因相同的概率不一样,因为它们相同的概率都是0。 现在,A有祖先A0和A1,A0和A1与B的相似程度分别为P(A0, B)和P(A1, B)。从祖先一代开始归纳,可由归纳假设A0与B、A1与B之间每个基因相同的概率都是

14、一样的,分别都是P(A0, B)和P(A1, B)。A的单个基因,它可能是继承A0的,也可能是继承A1的,概率各50%。继承A0的话与B相同的概率是P(A0, B),继承A1的话与B相同的概率是P(A1, B)。那么这个基因与B相同的概率就是: (P(A0, B)+P(A1, B)/2因此,A的每个基因与B相同的概率都是(P(A0, B)+P(A1, B)/2,具有相同的概率。进而,A与B相同基因的数量概率平均也为(P(A0, B)+P(A1, B)/2,A与B的相似程度 P(A, B)=(P(A0, B)+P(A1, B)/2 这样就归纳证明了P(A, B)的概率递推公式。 下面总结一下前面

15、得出的结论: (1)边界条件: A=B:P(A, B)1; A与B无相同基因:P(A, B)=0; (2)递推关系: P(A, B)(P(A0, B)+P(A1, B)/2,其中A0和A1是A的父母 有了边界条件和递推关系,以及Family Tree的阶段性和无后效性作为前提,用动态规划解决问题的所有条件都已满足。应该说,从理论上来讲,本题已经完全解决。下面需要讨论的仅仅是实现方法而已。 动态规划的实现方法有两种:一种是逆向的递推,另一种是正向的记忆化搜索(递归)。这两种方法都是可行的,区别仅仅在于,递推需要更多的考虑状态的阶段性,按照阶段计算出所有状态的值;而记忆化搜索只需要承认状态具有阶段

16、性,无需考虑阶段,只需要按照递推式本身设计带记忆化的递归函数即可。 本题给出的仅仅是一棵Family Tree,并没有给出Family Tree的阶段,如果要用递推的话,就必须先给Family Tree分阶段(拓扑排序)。所以,本题显然更适合用记忆化搜索来实现。 另外,需要注意的是,本题所求的答案是有多少精度就输出多少精度。300个节点的图,少说也可以构成几十层的Family Tree,算出的结果至少也有小数点后几十位。所以,高精度是必不可少的(保险起见,可以设置300位的高精度)。 分析一下本题的时间复杂度。动态规划的状态有n2个,转移代价为O(C)(高精度计算的代价)。因此,时间复杂度为为

17、O(Cn2),n300。 严格的讲,本题的算法不能算动态规划的方法,因为本题不存在最优化,应该仅仅是一个递推。不过,从分析问题的过程来看,它里面包含了很多动态规划的思想,例如,阶段性和无后效性,特别是使用了动态规划的一种实现方法记忆化搜索。8.3 尼克的任务源程序名 lignja.?(pas, c, cpp)可执行文件名 lignja.exe输入文件名 lignja.in输出文件名 lignja.out【问题描述】 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。 尼克的一个工作日为N分钟,从第

18、一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完戍,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。 写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。【输入】 输入数据第一行含两个用空格隔开的整数N和K(1N10000,1K10000),N表示尼克的工作时间,单位为分钟,K表示任务总数。 接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从

19、第P分钟开始,持续时间为T分钟,其中1PN,1P+T-1N。【输出】 输出文件仅一行,包含一个整数,表示尼克可能获得的最大空暇时间。【样例】 lignja.in lignja.out 15 6 4 1 2 1 6 4 11 8 5 8 1 11 5【算法分析】 题目给定的数据规模十分巨大:1K10000。采用穷举方法显然是不合适的。根据求最大的空暇时间这一解题要求,先将K个任务放在一边,以分钟为阶段,设置minutei表示从第i分钟开始到最后一分钟所能获得的最大空暇时间,决定该值的因素主要是从第i分钟起到第n分钟选取哪几个任务,与i分钟以前开始的任务无关。由后往前逐一递推求各阶段的minute

20、值: (1)初始值minuten+1=0 (2)对于minutei,在任务表中若找不到从第i分钟开始做的任务,则minutei比minutei+1多出一分钟的空暇时间;若任务表中有一个或多个从第i分钟开始的任务,这时,如何选定其中的一个任务去做,使所获空暇时间最大,是求解的关键。下面我们举例说明。 设任务表中第i分钟开始的任务有下列3个: 任务K1 P1=i T1=5 任务K2 P2=i T2=8 任务K3 P3=i T3=7 而已经获得的后面的minute值如下: minutei+5=4,minutei+8=5,minutei+7=3 若选任务K1,则从第i分钟到第i+1分钟无空暇。这时从第

21、i分钟开始能获得的空暇时间与第i+5分钟开始获得的空暇时间相同。因为从第i分钟到i+5-1分钟这时段中在做任务K1,无空暇。因此,minutei=minutei+54。 同样,若做任务K2,这时的minutei=minutei+8=5 若做任务K3,这时的minutei=minute1+7=3 显然选任务K2,所得的空暇时间最大。 因此,有下面的状态转移方程: 其中,Tj表示从第i分钟开始的任务所持续的时间。 下面是题目所给样例的minute值的求解。任务编号K123456开始时间P1148811持续时间T2611515时刻I16151413121110987654321minutei0123

22、401234561234选任务号k0000060040003002注:选任务号为该时刻开始做的任务之一,0表示无该时刻开始的任务。 问题所求得最后结果为从第1分钟开始到最后时刻所获最大的空暇时间minute1。 主要算法描述如下: (1)数据结构 var p:array1.10000of integer; 任务开始时间 t:array1.10000of integer; 任务持续时间 minute:array0.10001of integer; 各阶段最大空暇时间 (2)数据读入 readln(n, k); 读入总的工作时间n及任务k 读入k个任务信息 for i:=1 to k do rea

23、dln(pi,ti); 假设任务的开始时间按有小到大排列 (3)递推求minutei j:=k; 从最后一个任务选起 for i:=n downto 1 do begin minutei:=0; if pii then minutei:=1+minutei+1 无任务可选 else while pj=i do 有从i分钟开始的任务 begin if minutei+tjminutei then minutei:=minutei+tj; 求最大空暇时间 j:=j-1; 下一个任务 end; end; (4)输出解 writeln(minute1);8.4 书的复制 源程序名 book.?(pas

24、, c, cpp)可执行文件名 book.exe输入文件名 book.in输出文件名 book.out【问题描述】 现在要把m本有顺序的书分给k给人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。 现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。【输入】 第一行两个整数m,k;(km500) 第二行m个整数,第i个整数表示第i本书的页数。【输出】 共k行,每行两个整数,第i行表示第i个人抄写的书的起始编号和终止编号。k行的起始编号应该从小到大排列,如果有多解

25、,则尽可能让前面的人少抄写。【样例】 book.in book.out 9 3 1 5 1 2 3 4 5 6 7 8 9 6 7 8 9【问题分析】 本题可以用动态规划解决,但是动态规划并不是一个聪明的方法,这个后面会提到。不管怎样,我们还是先介绍动态规划的方法。 设f(n, k)为前n本书交由k个人抄写,需要的最短时间,则状态转移方程为 f(n, k)=minmaxf(i, k-1), , i=1, 2, , n-1 状态数为nk,转移代价为O(n),故时间复杂度为O(n2k)。 不难看出,上述方程满足四边形不等式,所以如果利用四边形不等式的性质,转移代价由平摊分析可得平均为O(1)。因此

26、,时间复杂度可以降为O(nk)。 动态规划求出的仅仅是最优值,如果要输出具体方案,还需根据动态规划计算得到的最优值,做一个贪心设计。具体来说,设最优值为T,那么k个人,每个人抄写最多T页。按顺序将书分配给k人去抄写,从第一个人开始,如果他还能写,就给他;否则第一个人工作分配完毕,开始分配第二个人的工作;以后再是第三个、第四个、直至第k个。一遍贪心结束后,具体的分配方案也就出来了。贪心部分的复杂度是O(n)的。 从前面的分析可以看到,动态规划部分仅仅是求出了一个最优值,具体方案是通过贪心求得的。而动态规划这部分的时间复杂度却是相当之高,所以用动态规划来求最优值是很不合算的。可以看到,当每人抄写的

27、页数T单调增加时,需要的人数单调减少,这就符合了二分法的基本要求。我们可以对T二分枚举,对每个枚举的T,用贪心法既求出需要的人数又求出具体的方案。所以,通过二分就能求得需要人数为k的最小的Tmin和相应的方案了。时间复杂度为O(nlog2c),c为所有书本的页数和。 从这道题目的解题过程中,我们可以看到动态规划也不是万金油,有时更一般的方法却可以得到更好的结果。8.5 多米诺骨源程序名 dom.?(pas, c, cpp)可执行文件名 dom.exe输入文件名 dom.in输出文件名 dom.out【问题描述】 多米诺骨牌有上下2个方块组成,每个方块中有16个点。现有排成行的n个多米诺骨牌如图

28、8-1所示。 上方块中点数之和记为,下方块中点数之和记为,它们的差为。例如在图8-1中, =6+1+1+1=9, =1+5+3+2=11, =2。每个多米诺骨牌可以旋转180,使得上下两个方块互换位置。 编程用最少的旋转次数使多米诺骨牌上下2行点数之差达到最小。 对于图8-1中的例子,只要将最后一个多米诺骨牌旋转180,可使上下2行点数之差为0。【输入】 输入文件的第一行是一个正整数n(1n1000),表示多米诺骨牌数。接下来的n行表示n个多米诺骨牌的点数。每行有两个用空格隔开的正整数,表示多米诺骨牌上下方块中的点数a和b,且1a,b6。【输出】 输出文件仅一行,包含一个整数。表示求得的最小旋转次数。【样例】 dom.in dom.out 4 1 6 1 1 5 1 3 1 2【问题分析】 本问题可归约为经典的背包问题。

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

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