版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、动态规划Dynamic Programming唐陈兴2007.12.30动态规划的基本思想动态规划算法通常用于求解具有某种最优性质的问题。在 这类问题中,可能会有许多可行解。每一个解都对应于一 个值,我们希望找到具有最优值的解。动态规划算法与分 治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题 的解。与分治法不同的是,适合于用动态规划求解的问题, 经分解得到子问题往往不是互相独立的。若用分治法来解 这类问题,则分解得到的子问题数目太多,有些子问题被 重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再 找出已求得的答案,这样就
2、可以避免大量的重复计算,节 省时间。我们可以用一个表来记录所有已解的子问题的答 案。不管该子问题以后是否被用到,只要它被计算过,就 将其结果填入表中。这就是动态规划法的基本思路。具体 的动态规划算法多种多样,但它们具有相同的填表格式。动态规划法一般步骤1、找出最优解的性质,并刻画其结构特征;2、递归地定义最优值(写出动态规划方程);3、以自底向上的方式计算出最优值;4、根据计算最优值时得到的信息,构造一个最优解。步骤1-3是动态规划算法的基本步骤。在只需要求出最优值的情形,步骤4可以省略,步骤3中记录的信息也较少;若需要求出问题的一个最优解, 则必须执行步骤4,步骤3中记录的信息必须足够多以便
3、构造最优解。动态规划问题的特征动态规划算法的有效性依赖于问题本身所具有的两个重要性质:最优子结构性质和子问题重叠性质。1、最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。2、重叠子问题:在用递归算法自顶向下解问题时, 每次产生的子问题并不总是新问题,有些子问题 被反复计算多次。动态规划算法正是利用了这种 子问题的重叠性质,对每一个子问题只解一次, 而后将其解保存在一个表格中,在以后尽可能多 地利用这些子问题的解。从一个简单的问题入手n FOJ1004 Number Trianglen 求人从顶端到底部,每次只能向左下右下走,最多能取得的值.数据规模: 行数1=R
4、=1000数塔中数值0.100 如图最优解为 7-3-8-7-5 =30从一个简单的问题入手n 状态表示用aij表示第i行第j列的值。用F(i,j)表示第i行第j列走到底部所能取得的最大值。而F(1,1)就是题目所求的答案。搜索源代码#include const int M=1000+5; int aMM,n;inline int max(int x,int y) return xy?y:x; int f(int i,int j)if (i=n) return aij;else return aij+max(f(i+1,j),f(i+1,j+1);int main() int i,j;whil
5、e(scanf(%d,&n)=1) for(i=1;i=n;i+)for(j=1;j=i;j+) scanf(%d,&aij);printf(%dn,f(1,1);return 0;从一个简单的问题入手n 人每次从顶部往下走,都有2种选择。n 如果搜索,到第n层的搜索量为为2n。n 1=n=1000,这种搜索量是从时间角度无法接受的。n 细心观察,不难发现实际上做了很多重复的搜索。用动态规划思想解决n 减少重复计算:自底向上。n 状态表示用aij表示第i行第j列的值。用Fij表示第i行第j列走到底部所能取得的最大值。而F11就是题目所求的答案。n 状态转移Fij=aij+max(Fi+1j,F
6、i+1j+1)动态规划源代码#include const int M=1000+5; int fMM,aMM;inline int max(int x,int y) return xy?y:x; int main()int i,j,n; while(scanf(%d,&n)=1)for(i=1;i=n;i+)for(j=1;j=i;j+) scanf(%d,&aij);for(j=1;j=1;i-)for(j=1;j=i;j+) fij=aij+max(fi+1j,fi+1j+1);printf(%dn,f11);return 0;记忆化搜索记忆化搜索:算法上依然是搜索的流程,但是搜索到的一些
7、解用动态规划的那种思想和模式作一些保存。一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下 来, 以后再次遇到这个状态的时候,就不必重新求解了。这种方法综合了搜索和动态规划两方面的优点, 因而还是很有实用价值的。记忆化搜索动态规划不仅需要推出状态转移方程式,还要进行拓扑排序。搜索相对于动态规划最大的劣势无非就是重复计算子结构,所以我们在搜索的过程中,对于每一个子结构只计算一次,之后保存到数组里,以后要用到的
8、时候直接调用就可以了。记忆化搜索的实质是动态规划,效率也和动态规划接近,形式是搜索,简单直观,代码也容易编写, 不需要进行什么拓扑排序了。可以归纳为:记忆化搜索=搜索的形式+动态规划的思想数塔记忆化搜索源代码#include#include const int M=1000+5;int aMM,n, ff MM;inline int max(int x,int y) return xy?y:x; int f(int i,int j)if (ffij!=-1) return ffij;if (i=n) return aij;else return ffij=aij+max(f(i+1,j),f(
9、i+1,j+1);int main()int i,j; while(scanf(%d,&n)=1)for(i=1;i=n;i+) for(j=1;j=i;j+) memset(ff,-1,sizeof(ff);printf(%dn,f(1,1);return 0;scanf(%d,&aij);FOJ1320 Onesn 给一个整数n,要你找一个值为n的表达式, 这个表达式只有1 + * ( ) 够成。并且1不能连续,比如11+1就不合法。n 输入n,(1=n=10000)n 输出最少需要多少个1才能构成表达式。n 样例:n=2=1+1ans=2ans=7n=10=(1+1)*(1+1+1+1+
10、1)Ones让fi表示最少数量的1能够表示i。add:fi=fj+fi-j0jimultiply: fi=fj+fi/j0ji, i%j=0for(i=1;i=n;i+) fi=i; for(j=1;ji;j+)fi=min(fi,fj+fi-j);if (i%j=0) fi=min(fj+fi-j);O(n2) n=10000Onesn How to improve?n For multiply, 1j*ji.n fi=minfj+fi/j+fi%j 1j*jin O(n1.5)1=n=10000n n1.5=1,000,000n 算法时间可以以计算机每秒执行8,000,000语句进行估算。
11、Ones源代码#include #include int f10001;int main() int i,j,tmp,r;for(i=1;i=10000;i+)r=sqrt(i); fi=i; for(j=2;j=r;j+)tmp=fi%j+fj+fi/j;if(tmpfi) fi=tmp;while(scanf(%d,&i)!=EOF) printf(%dn,fi); return 0;FOJ1319 Blocks ofStonesn 经典的石子归并问题有n (1=n7 1-8 分数7+8=15合并方案二: 2 5 1-2 6-8 分数6+8=14FOJ1319 Blocks ofStone
12、sn 状态表示:n 用ai 表示初始时每堆石子的个数。n 用si表示初始时从第1堆到第i堆石子的总和。n 用fij(i=j)表示从第i堆合并到第j堆的最小分数。fij=minfi,k-1+fk,j+wi,j;n wij=sumaiaj=sj-si-1;n 这样枚举是n3的。FOJ1319 Blocks ofStonesn fij=minfi,k-1+fk,j+wi,j;n 改进k的取值范围:Let s(i,j)=maxk|arg minfi,js(i,j-1)=k=s(i+1,j) O(n2)n FOJ1319 Blocks ofStonesn 另外,FOJ1319可以交换任意两个相邻的石堆,
13、这步可以通过O(n)的枚举来实现。FOJ1348 Longest Ordered Subsequencen 最长递增子序列n 给一个序列,求它的一个最长递增子序列。递增序列满足:a1 a2 . aNn 例如序列(1, 7, 3, 5, 9, 4, 8) 的递增子序列有(1, 7), (3, 4, 8) (1,3,4,8) 其中(1,3,4,8)为最长递增子序列。n 求给定的序列中最长递增子序列的长度。n (最长递增子序列未必唯一)O(n2)设fi表示:序列L中以ai为末元素的最长递增子序列的长度。在求以ai为末元素的最长递增子序列时,找到所有序号在序列L前面且小于ai的元素aj,即ji且aja
14、i。如果这样的元素存在,那么对所有aj,都有一个以aj 为末元素的最长递增子序列的长度fj,把其中最大的fj选出来,那么fi就等于最大的fj加上1, 即以ai为末元素的最长递增子序列,等于以使fj最大的那个aj为末元素的递增子序列最末再加上ai; 如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。#include int main()int i,j,n,a1001,f1001,ans;while(scanf(%d,&n)!=EOF)for(i=1;i=1;i-)fi=1;for(j=i+1;j=n;j+)if (aiaj & fifj+1) fi=fj+1;n f
15、i= x, x, x, x, x, 2, 1n fi= x, x, x, x, 1, 2, 1n fi= x, x, x, 2, 1, 2, 1n fi= x, x, 3, 2, 1, 2, 1n fi= x, 2, 3, 2, 1, 2, 1n fi= 4, 2, 3, 2, 1, 2, 1ans=0;for(i=1;i=n;i+) if (ansfi) ans=fi; printf(%dn,ans);return 0;O(n*log(n)对算法的改进在上述算法中,在计算每一个fi时,都要找出最大的fj(ji)来,由于fj没有顺序,只能顺序查找满足ajai最大的fj,如果能将让fj有序,就可
16、以使用二分查找,这样算法的时间复杂度就可能降到O(nlogn)。于是想到用一个数组b来存储“子序列的”最大递增子序列的最末元素,即有bfj = aj在计算fi时,在数组b中用二分查找法找到满足ji且bfj=ajai的最大的j,并将bfj+1置为ain 样例说明:n ai= 1, 7, 3, 5, 9, 4, 8n b=1n b=1,7n b=1,3n b=1,3,5n b=1,3,5,9n b=1,3,4,9n b=1,3,4,8源代码/LIS 最长递增序列n*log(n)int LIS (int *a,int n)int ans,i,k,*b=new int n+1; bans=0=-0x7
17、fffffff;for(i=0;ians) b+ans=ai;else if (bkai) bk=ai;delete b; return ans;FOJ1147 Tilingn In how many ways can you tile a 2 x n rectangle by 2 x 1 or 2 x 2 tiles?n Here is a sample tiling ofa 2 x 17 rectangle.n Input is a sequence oflines, each line containing an integer number 0 = n = 250. For each
18、line ofinput, output one integer number in a separate line giving the number ofpossible tilings ofa 2xn rectangle.n 状态表示:Fn表示2 x n的走道上铺满1 x 2, 2 x 2 的砖块的方法数量n 考虑最后一块砖和最后两块砖的放法,很容易写出DP状态转移方程。n Fi=Fi-1+Fi-2+Fi-2, 边界:F0=F1=1;n 最后一块1 x 2竖放:Fi-1n 最后两块1 x 2横放:Fi-2n 最后放一块 2 x 2的:Fi-2n 另外: n = 250,需要高精度FOJ1
19、342 Tight Wordsn Given is an alphabet 0, 1, . , k, 0 = k = 9 .We say that a word oflength n over this alphabet is tight ifany two neighbour digits inthe word do not differ by more than 1.n Input is a sequence oflines, each line contains two integer numbers k and n, 1 = n = 100. For each line ofinput
20、, output the percentage of tight words oflength n over the alphabet 0,1, . , k with 5 fractional digits.FOJ1342 Tight Wordsn 紧密单词:单词中任何相邻位置的数字相差不超过1。n 长度为n,由0.k组成的单词中,紧密单词的百分比。(1=n=100,0=k=9)n 例如k=2, n=2 的单词共有(k+1)n=32=9个。n 其中紧密单词有7个:00,01,10,11,12,21,22n 非紧密单词有2个:02,20n 百分比为7/9=77.77778%FOJ1342 Tig
21、ht Wordsn 长度为n,由0.k组成的单词共有(k+1)n 个, (1=n=100,0=k=9)。枚举所有的单词显然是不可能的。O(k+1)*n)空间,O(k+1)*n)时间n 在使用数字0.k构造单词的条件下,Fij表示单词长度为i,以数字j为基本单词产生的紧密单词的百分比。n Fi0=(Fi-1j+Fi-1j+1)/(k+1);n Fij=(Fi-1j-1+Fi-1j+Fi-1j+1)/(k+1);n Fik=(Fi-1j-1+Fi-1j+1)/(k+1);#include #include double f10010; double tot; int main()int i,j,k
22、,n;while (scanf(%d %d,&k,&n)!=EOF)k+;memset(f,0,sizeof(f);for (i=0;ik;i+) f0i=100.0/k;for (i=1;in;i+)fi0=fi-10/k;for (j=1;jk;j+) fij+=(fi-1j+fi-1j-1)/k; for (j=0;jk-1;j+) fij+=fi-1j+1/k;tot=0;for (i=0;i1),则由长度为n-1的概率添加头 尾得到n tmp0=(f0+f1)/(k+1);n tmpi=(fi-1+fi+fi+1)/(k+1);n tmpk=(fk-1+fk)/(k+1);n mem
23、cpy(f,tmp,sizeof(double)*(k+1);n for(ans=0.0,i=0;i=k;i+) ans+=fi;#include stdio.h int main()double f10,temp10,ans; int k,n,i,t;while(scanf(%d%d,&k,&n)!=EOF) for(i=0;i=k;i+) fi=100.0/(k+1);for(t=2;t=n;t+) temp0=(f0+f1)/(k+1);for(i=1;i=k-1;i+) tempi=(fi-1+fi+fi+1)/(k+1); tempk=(fk-1+fk)/(k+1);for(i=0;
24、i=k;i+) fi=tempi;for(ans=0.0,i=0;i=k;i+) ans+=fi; printf(%0.5lfn,ans);return 0;FOJ1559 Count Zerosn 正整数可以表示为2进制。计算1.2n中,这 些正整数以2进制表示时共有多少个0. (1=n111的过程,而10000还有右数第4的1没有被计算过,所以结果还要加1。FOJ1523 A Version ofNimn 可以用DP解决的一类博弈问题n 问题描述: 有4堆石子每堆最多9个,2个人轮流取石子,每次可以且必须取其中1堆的1-3个石子,取得最后一个石子的人失败,假设双方都采用最优策略,问先手胜败
25、。局面n 必败局:无论如何取石子,其子状态都是必胜局。n 必胜局:存在一种或一种以上的取法,使得其子状态为必败局。n 对于本题,典型的必败局有(1,0,0,0),(5,0,0,0) n 必胜局有(2,0,0,0),(3,0,0,0),(4,0,0,0),(1,1,0,0)FOJ1523 A Version ofNim四堆石子(x,y,i,j)Fxyij=1表示先手必胜,0表示先手必败。if (x=0 & y=0 & i=0 & j=0) Fijxy=1; if (!ff(i-1,j,x,y) | !ff(i-2,j,x,y) | !ff(i-3,j,x,y)| !ff(i,j-1,x,y) |
26、 !ff(i,j-2,x,y) | !ff(i,j-3,x,y)| !ff(i,j,x-1,y) | !ff(i,j,x-2,y) | !ff(i,j,x-3,y)| !ff(i,j,x,y-1) | !ff(i,j,x,y-2) | !ff(i,j,x,y-3) Fijxy=1;else Fijxy=0;int ff(int i,int j,int x,int y)if (i0 | j0 | x0 | y0) return 1; else return fijxy;FOJ1381 Regular Expressionsn You are given two regular expressions R1 and R2 and should find minimal string S matching both. String consists o
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026四年级数学上册 综合练习三
- 【 生物 】人与自然和谐共生教学课件-2025-2026学年人教版生物八年级下册
- 髌骨骨折康复宣教
- 2023年浙江自贸区海泰石化科技有限公司招聘考试真题
- 广电系统消防安全培训方案
- 青霉素使用须知
- 期中考试后教师会议上校长的讲话:以考促教抓落实深耕细研提质效
- 2024工程维修简单的合同范本
- 2024-2025学年高二数学上学期期末-专题07 数列的概念与通项公式(解析版) 人教A
- 2023年普通高等学校招生全国统一考试模拟考试语文试题及答案
- 2026年一级建造师《建设工程项目管理》真题及答案
- GB/T 47241-2026虚拟电厂技术导则
- 官兵心理健康档案模版
- GB/T 8834-2006绳索有关物理和机械性能的测定
- 高三化学人教版2016二轮复习专题八 电化学原理
- GB/T 15055-2021冲压件未注公差尺寸极限偏差
- B.2工程项目招标控制价封面(封-2)
- 基础工程连续基础课件
- 真分数和假分数-完整版课件
- 安全隐患整改通知回执单-三联
- 1.《郑人买履》课件PPT
评论
0/150
提交评论