45道动态规划题目分析
动态规划练习试题和解答
动态规划练习题[题1] 多米诺骨牌(DOMINO)问题描述:有一种多米诺骨牌是平面的,其正面被分成上下两部分,每一部分的表面或者为空,或者被标上1至6个点。
现有一行排列在桌面上:顶行骨牌的点数之和为6+1+1+1=9;底行骨牌点数之和为1+5+3+2=11。
顶行和底行的差值是2。
这个差值是两行点数之和的差的绝对值。
每个多米诺骨牌都可以上下倒置转换,即上部变为下部,下部变为上部。
现在的任务是,以最少的翻转次数,使得顶行和底行之间的差值最小。
对于上面这个例子,我们只需翻转最后一个骨牌,就可以使得顶行和底行的差值为0,所以例子的答案为1。
输入格式:文件的第一行是一个整数n(1〈=n〈=1000〉,表示有n个多米诺骨牌在桌面上排成一行。
接下来共有n行,每行包含两个整数a、b(0〈=a、b〈=6,中间用空格分开〉。
第I+1行的a、b分别表示第I个多米诺骨牌的上部与下部的点数(0表示空)。
输出格式:只有一个整数在文件的第一行。
这个整数表示翻动骨牌的最少次数,从而使得顶行和底行的差值最小。
[题2] Perform巡回演出题目描述:Flute市的Phlharmoniker乐团2000年准备到Harp市做一次大型演出,本着普及古典音乐的目的,乐团指挥L.Y.M准备在到达Harp市之前先在周围一些小城市作一段时间的巡回演出,此后的几天里,音乐家们将每天搭乘一个航班从一个城市飞到另一个城市,最后才到达目的地Harp市(乐团可多次在同一城市演出).由于航线的费用和班次每天都在变,城市和城市之间都有一份循环的航班表,每一时间,每一方向,航班表循环的周期都可能不同.现要求寻找一张花费费用最小的演出表.输入: 输入文件包括若干个场景.每个场景的描述由一对整数n(2<=n<=10)和k(1<=k<=1000)开始,音乐家们要在这n个城市作巡回演出,城市用1..n标号,其中1是起点Flute市,n是终点Harp市,接下来有n*(n-1)份航班表,一份航班表一行,描述每对城市之间的航线和价格,第一组n-1份航班表对应从城市1到其他城市(2,3,...n)的航班,接下的n-1行是从城市2到其他城市(1,3,4...n)的航班,如此下去.每份航班又一个整数d(1<=d<=30)开始,表示航班表循环的周期,接下来的d个非负整数表示1,2...d天对应的两个城市的航班的价格,价格为零表示那天两个城市之间没有航班.例如"3 75 0 80"表示第一天机票价格是75KOI,第二天没有航班,第三天的机票是80KOI,然后循环:第四天又是75KOI,第五天没有航班,如此循环.输入文件由n=k=0的场景结束.输出:对每个场景如果乐团可能从城市1出发,每天都要飞往另一个城市,最后(经过k天)抵达城市n,则输出这k个航班价格之和的最小值.如果不可能存在这样的巡回演出路线,输出0.样例输入: 样例输出:3 6 4602 130 150 03 75 0 807 120 110 0 100 110 120 04 60 70 60 503 0 135 1402 70 802 32 0 701 800 0[题3] 复制书稿(BOOKS)问题描述:假设有M本书(编号为1,2,…M),想将每本复制一份,M本书的页数可能不同(分别是P1,P2,…PM)。
动态规划专项练习题解
另一种方法
• 将原串与原串的倒序做一次LCS—最长公 共子序列,用原串长度减去LCS长度,即 为需要插入字符的个数 • 例如:ab3bd与 db3ba • LCS(‘ab3bd’, ‘db3ba’)=‘b3b’ • 因此, ans=Len(‘ab3bd’)-Len(‘b3b’)=2
LCS的求法
• 最长公共子串(LCS),有三种情况: 1. 公共子串的元素必须相邻. 2. 公共子串的元素可以不相邻 3. 求多个字符串而不是两个字符串的最长公共 子串 • 动归4中,我们讲了求情况2的LCS序列。下面我们 来讨论情况1的做法。
• 任务:对于任意一个字符串,输出将这个字符串 变为回文串需要插入的最少字符个数,比如, ab3bd只需要插入2个字符就可以变为一个回文串. • 0<n<=1992,n为字符串长度。
分析
• ab3bd • 只需变为adb3bda即可,在前面插入d,在 后面插入a; • 我们分几种情况讨论:
– 若A形如 ?A?,(问号代表任意一个相同字符, 下同)则只需将A变为回文串。 – 若A形如?A再在A的后面插入一个”?” – 若A形如A ?再在A的前面插入一个”?”
分析
• 性质:青蛙遍历的路径不会相交。
• 上图中图2的路径比图1要短。 • 证明:图1: D1=d(1,3)+d(2,3)+d(2,4) 图2: D2=d(1,2)+d(2,3)+d(3,4) 要证明D1>D2,只要证明d(1,3) +d(2,4)>d(1,2)+d(3,4) 连接两边,见图3,由三角形的三边关系定理即可证明。
动态规划
• 设f(i,j)为将Ai..Aj变为回文串的最小代价,则
f (i 1, j 1), 若a[i] a[ j ] f (i, j ) min f (i 1, j ) 1, 若a[i] a[ j ],后插一个字符 f (i, j - 1) 1,若a[i] a[ j ],前插一个字符
动态规划的具体应用例题
动态规划的具体应用例题3.1 最长不降子序列(1)问题描述设有由n个不相同的整数组成的数列,记为:a(1)、a(2)、……、a(n)且a(i)<>a(j) (i<>j)例如3,18,7,14,10,12,23,41,16,24。
若存在i1<i2<i3< … < ie 且有a(i1)<a(i2)< … <a(ie)则称为长度为e的不下降序列。
如上例中3,18,23,24就是一个长度为4的不下降序列,同时也有3,7,10,12,16,24长度为6的不下降序列。
程序要求,当原数列给出之后,求出最长的不下降序列。
(2)算法分析根据动态规划的原理,由后往前进行搜索。
1· 对a(n)来说,由于它是最后一个数,所以当从a(n)开始查找时,只存在长度为1的不下降序列;2· 若从a(n-1)开始查找,则存在下面的两种可能性:①若a(n-1)<a(n)则存在长度为2的不下降序列a(n-1),a(n)。
②若a(n-1)>a(n)则存在长度为1的不下降序列a(n-1)或a(n)。
3· 一般若从a(i)开始,此时最长不下降序列应该按下列方法求出: 在a(i+1),a(i+2),…,a(n)中,找出一个比a(i)大的且最长的不下降序列,作为它的后继。
4.用数组b(i),c(i)分别记录点i到n的最长的不降子序列的长度和点i后继接点的编号(3) 程序如下:(逆推法)program li1;const maxn=100;var a,b,c:array[1..maxn] of integer;fname:string;f:text;n,i,j,max,p:integer;beginreadln(fname);assign(f,fname);reset(f);readln(f,n);+for i:=1 to n dobeginread(f,a[i]);b[n]:=1;c[n]:=0;end;for i:= n-1 downto 1 dobeginmax:=0;p:=0;for j:=i+1 to n doif (a[i]<a[j]) and (b[j]>max) then begin max:=b[j];p:=j end;if p<>0 then begin b[i]:=b[p]+1;c[i]:=p endend;max:=0;p:=0;for i:=1 to n doif b[i]>max then begin max:=b[i];p:=i end;writeln('maxlong=',max);write('result is:');while p<>0 dobegin write(a[p]:5);p:=c[p] end;end.3.2 背包问题背包问题有三种1.部分背包问题一个旅行者有一个最多能用m公斤的背包,现在有n种物品,它们的总重量分别是W1,W2,...,Wn,它们的总价值分别为C1,C2,...,Cn.求旅行者能获得最大总价值。
45道动态规划题目分析
分析
• d[i,j]表示是否有可能i和j相遇, 则第i个人能 取得最后的胜利当且仅当d[i,i]为true • 状态转移: 考虑相遇前的最后一步, 则d[I,j] 为true当且仅当
– 能找到一个k, 使得i能遇k, k能遇到j, 且 – i或者j能打败k
• 状态有O(n2)个, 转移有O(n)个, 共O(n3)
• 状态O(kn2)个, 决策O(n), 转移时间O(1)(先预处理), 总时间O(kn3)
机器人的名字
• 考虑一种基于重复子串的压缩方法 • 用[St]k表示k个相同的子串St(其中St称为重复子串, k是一个单字节整数,只占一个字符位置) • 如果这k个子串并没有连在一起,则可以在[St]k的 后面加上{S1}t1{S2} t2…{Sr} tr(1<ti<k,ti<ti+1), 表示在第ti个St的后面放置Si,Si称为插入子串 • St和Si也都可以是压缩后的字符串 • 比如I_am_WhatWhat_is_WhatWhat的压缩结果 为I_am_[What]4{_is_}2,长度为19 (例子中的空 格用下划线“_”表示,数字2和4实际上是用单字 节二进制表示的) • 名字不会以空格开始或结尾,大小写敏感
• 原棋盘上每一格有一个分值,一块矩形棋 盘的总分为其所含各格分值之和。现在需 要把棋盘按上述规则分割成n块矩形棋盘, 并使各矩形棋盘总分的均方差最小。
(a) 允许的分割方案
(b) 不允许的分割方案
分析
• 变形均方差公式
n n 1 1 n 2 2 ( n( x ) 2 x i 2 2 x x i ) x i ( x ) 2 n n i 1 i 1 i 1
– d[k-1,x1,y1,a,y2]+s[a+1,y1,x2,y2] – d[k-1,a+1,y1,x2,y2]+s[x1,y1,a,y2] – 其中x1<=a<=x2
动态规划-例题众多-详细讲解
步骤2:状态转移方程:
步骤3:以自底向上的方法来计算最优解
12
程序的实现
BuyTicks(T, R)
1 n ← length[T]
2 f[0] ← 0
3 f[1] ← T[1]
4 for i ← 2 to n do
5
f[i] ← f[i-2]+R[i-1]
6
if f[i] > f[i-1]+T[i] then
n 0 1 2 3 4 5 6 7 8 9 10 F(n) 1 1 2 3 5 8 13 21 34 55 89
2
递归 vs 动态规划
递归版本:
F(n)
1 if n=0 or n=1 then
2
return 1
3 else
4
return F(n-1) + F(n-2)
太慢!
动态规划:
F(n)
1 A[0] = A[1] ← 1
这里是某支股票的价格清单: 日期 1 2 3 4 5 6 7 8 9 10 11 12 价格 68 69 54 64 68 64 70 67 78 62 98 87 最优秀的投资者可以购买最多4次股票,可行方案中的一种是: 日期 2 5 6 10 价格 69 68 64 62 输入 第1行: N (1 <= N <= 5000),股票发行天数 第2行: N个数,是每天的股票价格。 输出 输出文件仅一行包含两个数:最大购买次数和拥有最大购买次数的方案数(<=231) 当二种方案“看起来一样”时(就是说它们构成的价格队列一样的时候),这2种方 案被认为是相同的。
你的任务是,已知所有N位同学的身高,计算最少需要 几位同学出列,可以使得剩下的同学排成合唱队形。
动态规划习题详解
动态规划动态规划是运筹学的一个分支,它是解决多阶段决策过程最优化问题的一种方法。
该方法是由美国数学家贝尔曼(R.Bellman)等人在本世纪50年代初提出的。
他们针对多阶段决策问题的特点,提出了解决这类问题的“最优化原理”,并成功地解决了生产管理、工程技术等方面的许多实际问题,从而建立了运筹学的一个新分支——动态规划。
他的名著《动态规划》于1957年出版,该书是动态规划的第一本著作。
动态规划是现代企业管理中的一种重要决策方法,在工程技术、经济管理、工农业生产及军事及其它部们都有广泛的应用,并且获得了显著的效果。
动态规划可用于解决最优路径问题、资源分配问题、生产计划与库存问题、投资分配问题、装载问题、设备更新与维修问题、排序问题及生产过程的最优控制等。
由于它所具有独特的解题思路,在处理某些优化问题时,常常比线性规划或非线性规划方法更有效。
第一节动态规划的基本方法多阶段决策的实际问题很多,下面通过具体例子,说明什么是动态规划模型及其求解方法。
例1:最短路线问题某工厂需要把一批货物从城市A运到城市E,中间可经过B1 、B2、B3、C1、C2、C3、D1、D2等城市,各城市之间的交通线和距离如下图所示,问应该选择一条什么路线,使得从A到E的距离最短?下面引进几个动态规划的基本概念和相关符号。
(1)阶段(Stage)把所给问题的过程,按时间和空间特征划分成若干个相互联系的阶段,以便按次序去求每个阶段的解,阶段总数一般用字母n表示,用字母k表示阶段变量。
如例l中 (最短路线问题)可看作是n=4阶段的动态规划问题,k=2表示处于第二阶段。
(2)状态(State)状态表示每个阶段开始时系统所处的自然状况或客观条件,它描述了研究问题过程状况。
描述各阶段状态的变量称为状态变量,常用字母sk表示第k阶段的状态变量,状态变量的取值范围称为状态集,用Sk表示。
如例l中,第一阶段的状态为A(即出发位置)。
第二阶段有三个状态:B1 、B2、B3,状态变量s2=B2表示第2阶段系统所处的位置是B2。
动态规划总结经典题目(经典中的经典)
动态规划总结——经典问题总结本文着重讨论状态是如何表示,以及方程是怎样表示的。
当然,还附上关键的,有可能作为模板的代码段。
但有的代码的实现是优化版的。
经典问题总结最长上升子序列(LIS)问题描述如下:设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。
求最大的m值。
这里采用的是逆向思维的方法,从最后一个开始想起,即先从A[N](A数组是存放数据的数组,下同)开始,则只有长度为1的子序列,到A[N-1]时就有两种情况,如果a[n-1] < a[n] 则存在长度为2的不下降子序列a[n-1],a[n];如果a[n-1] > a[n] 则存在长度为1的不下降子序列a[n-1]或者a[n]。
有了以上的思想,DP方程就呼之欲出了(这里是顺序推的,不是逆序的):DP[I]=MAX(1,DP[J]+1)J=0,1,...,I-1但这样的想法实现起来是)O(n^2)的。
本题还有更好的解法,就是O(n*logn)。
利用了长升子序列的性质来优化,以下是优化版的代码://最长不降子序const int SIZE=500001;int data[SIZE];int dp[SIZE];//返回值是最长不降子序列的最大长度,复杂度O(N*logN)int LCS(int n) { //N是DATA数组的长度,下标从1开始int len(1),low,high,mid,i;dp[1]=data[1];for(i=1;i<=n;++i) {low=1;high=len;while( low<=high ) { //二分mid=(low+high)/2;if( data[i]>dp[mid] ) {low=mid+1;}else {high=mid-1;}}dp[low]=data[i];if( low>len ) {++len;}}return len;}最长公共子序列(LCS)给出两个字符串a, b,求它们的最长、连续的公共字串。
动态规划经典题目分析
寻宝游戏
SAMPLE INPUT 55 00010 10000 01000 00020 00000 6 101211 SAMPLE OUTPUT 3 数据范围 2≤N、M≤100,1≤Len≤250。表格和数列中的每一项都小于100。
分析
设F[i,x,y]表示ai与表格中位于(x,y)的数向对 应,且数列{ai}的前1~i-1项与表格中所有bi 位置为(x,y)的数列的最小接近程度。 B1和B2~Bn是有点不一样的。 因为B2~Bn都和前面的数有位置关系,而 B1没有。 所以初始化条件为 F[1,x,y]=(a[1]-table[x,y])2
代码
program CQF_CMI; var value,last:array[0..200000] of longint; n:longint; procedure init; var i,j:longint; begin readln(n); for i:=1 to n do read(value[i]); readln; end;
数字游戏
小W发明了一个游戏,他在黑板上写出了一行 数字a1,a2,a3,……,an,然后给你M个回合 的机会,每会回你可以从中选择一个数字擦去它, 接着剩下来的每个数字ai都要递减一个值bi。如此 重复m个回合,所有你擦去的数字之和就是你所 得的分数。 小W和他的好朋友小Y玩了这个游戏,可是他 发现,对于每个给出的a和b序列,小Y的得分总 比他高,所以他就很不服气。于是他想让你帮他 算算,对于每个a和b序列,可以得到的最大得分 是多少。
算法
建立一个数组last。 Last[i]表示长度为i的子序列中最小的最后一 个数。 特别的last[0]=负无穷 假如现在已经处理了前i-1个数,考虑加入 第i个数。
动态规划经典题目分析共37页
xiexie! 38、我这个人走得很慢,但是我从不后退。——亚伯拉罕·林肯
39、勿问成功的秘诀为何,且尽全力做你应该做的事吧。——美华纳
40、学而不思则罔,思而不学则殆。——孔子
39、没有不老的誓言,没有不变的承 诺,踏 上旅途 ,义无 反顾。 40、对时间的价值没有没有深切认识 的人, 决不会 坚韧勤 勉。
谢谢!
36、自己的鞋子,自己知道紧在哪里。——西班牙
37、我们唯一不会改正的缺点是软弱。——拉罗什福科
动态规划经典题目分析
36、“不可能”这个字(法语是一个字 ),只 在愚人 的字典 中找得 到。--拿 破仑。 37、不要生气要争气,不要看破要突 破,不 要嫉妒 要欣赏 ,不要 托延要 积极, 不要心 动要行 动。 38、勤奋,机会,乐观是成功的三要 素。(注 意:传 统观念 认为勤 奋和机 会是成 功的要 素,但 是经过 统计学 和成功 人士的 分析得 出,乐 观是成 功的第 三要素 。
(完整版)动态规划问题常见解法
(完整版)动态规划问题常见解法动态规划问题常见解法一、背包问题1. 0/1背包问题0/1背包问题是动态规划中的经典问题,解决的是在背包容量固定的情况下,如何选择物品放入背包,使得总价值最大化。
常见的解法有两种:记忆化搜索和动态规划。
记忆化搜索是一种自顶向下的解法,通过保存子问题的解来避免重复计算,提高效率。
动态规划是一种自底向上的解法,通过填表格的方式记录每个子问题的解,最终得到整个问题的最优解。
2. 完全背包问题完全背包问题是在背包容量固定的情况下,如何选择物品放入背包,使得总价值最大化,且每种物品可以选择任意个。
常见的解法有两种:记忆化搜索和动态规划。
记忆化搜索和动态规划的思路和0/1背包问题相似,只是在状态转移方程上有所不同。
二、最长公共子序列问题最长公共子序列问题是指给定两个序列,求它们之间最长的公共子序列的长度。
常见的解法有两种:递归和动态规划。
递归的思路是通过分别考虑两个序列末尾元素是否相等来进一步缩小问题规模,直至问题规模减小到边界情况。
动态规划的思路是通过填表格的方式记录每个子问题的解,最终得到整个问题的最优解。
三、最短路径问题最短路径问题是指在加权有向图或无向图中,求解从一个顶点到另一个顶点的最短路径的问题。
常见的解法有两种:Dijkstra算法和Bellman-Ford算法。
Dijkstra算法是通过维护一个距离表,不断选择距离最短的顶点来更新距离表,直至找到目标顶点。
Bellman-Ford算法是通过进行多次松弛操作,逐步缩小问题规模,直至找到目标顶点或发现负权环。
总结:动态规划是一种解决最优化问题的常见方法,它通过分组子问题、定义状态、确定状态转移方程和填表格的方式,来得到整个问题的最优解。
在解决动态规划问题时,可以采用记忆化搜索或者动态规划的策略,具体选择哪种方法可以根据问题的特点和优化的需要来决定。
动态规划讲解大全(含例题及答案)
多阶段决策过程的最优化问题。 在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在 它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。当然,各个阶段决策的选取不 是任意确定的,它依赖于当前面临的状态,又影响以后的发展,当各个阶段决策确定后,就组成一个 决策序列,因而也就确定了整个过程的一条活动路线,如图所示:(看词条图) 这种把一个问题看作是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这种问 题就称为多阶段决策问题。
在前面的例子中,第一个阶段就是点 A,而第二个阶段就是点 A 到点 B,第三个阶段是点 B 到点 C,而第四个阶段是点 C 到点 D。
状态:状态表示每个阶段开始面临的自然状况或客观条件,它不以人们的主观意志为转移,也称 为不可控因素。在上面的例子中状态就是某阶段的出发位置,它既是该阶段某路的起点,同时又是前 一阶段某支路的终点。
fout.close(); return 0; }
USACO 2.3 Longest Prefix
题目如下: 在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序 列分解成较短的(称之为元素的)序列很感兴趣。 如果一个集合 P 中的元素可以通过串联(允许重复;串联,相当于 Pascal 中的 “+” 运算符) 组成一个序列 S ,那么我们认为序列 S 可以分解为 P 中的元素。并不是所有的元素都必须出现。 举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素: {A, AB, BA, CA, BBC} 序列 S 的前面 K 个字符称作 S 中长度为 K 的前缀。设计一个程序,输入一个元素集合以及一 个大写字母序列,计算这个序列最长的前缀的长度。 PROGRAM NAME: prefix INPUT FORMAT 输入数据的开头包括 1..200 个元素(长度为 1..10 )组成的集合,用连续的以空格分开的字 符串表示。字母全部是大写,数据可能不止一行。元素集合结束的标志是一个只包含一个 “.” 的行。 集合中的元素没有重复。接着是大写字母序列 S ,长度为 1..200,000 ,用一行或者多行的字符串 来表示,每行不超过 76 个字符。换行符并不是序列 S 的一部分。 SAMPLE INPUT (file prefix.in) A AB BA CA BBC . ABABACABAABC OUTPUT FORMAT 只有一行,输出一个整数,表示 S 能够分解成 P 中元素的最长前缀的长度。 SAMPLE OUTPUT (file prefix.out) 11 示例程序如下: #include <stdio.h>
动态规划题目分析
对于这题目输出方案,我们可以用记录某个状 态是由那个状态得到的,这样我们可以得到方 案数。 那么怎样求最大的叠放数呢?我们不妨倒过来 分析:F[i,j]表示后面编号为I到N的物品到达重 量为J时最多可以放多少个物品,方程为: F[I,j]=max(f[i+1,j-m[i]]+1(满足jm[i]<=w[i]),f[i+1,j]),我们再用La[I,j]记录这个 状态是由f[i+1,la[I,j]]得到的。 时间复杂度为:O(3000N)
走道铺砖(floor)
给你N*M的图(N*M为偶数),然后用 1*2的方块把这个图全部铺满。 问有多少个不同本质的方案。 Min(n,m)<=12;n,m<=40;
题目分析
可以知道:N,M中有一个特别小。 我们就可以用状态压缩的动态规划来求 解。 首先对某一列分析,这一列可能有些格 子已经被占领,那么其它的格子要么被 方块横放,要么被方块竖放,那么下一 列的初始状态可以搜索出来。
题目分析
我们可以把这个矩阵变为一个图,每个 格子看成一个点,如果某个格子能够到 另外一个格子,则连一条有向边。 我们可以看到这是一个有向图,那么对 于某个点有影响的点是数字比它小的点。
题目分析
那么我们可以得到方程: F[i,j]=max(f[x,y])+a[i,j](点(x,y)能够到达点(i,j)) 那么方程怎么实现转移呢? 我们可以分析,如果当某个点被扩展时,那么这个点 要达到最优状态,及这个点不能被其它没扩展的点到 达。 怎样处理呢?我们知道当某个点的数比这个数小时, 就有可能到达这个点,我们就可以先把这些点从小到 大排序,然后一次处理即可。 处理时是像广搜一样由已知状态扩展到未知状态, 时间复杂度:O(NNK);
动态规划例题讲解
最长上升子序列
算法:动态规划 令f[i]表示以ai为结尾的最长上升子序列的长 度 转移方程: f[i]=max(f[j],1<=j<i,a[j]<a[i])+1 时间复杂度:O(N^2)
最长上升子序列
换一种状态表示方法 令f[i]表示长度为i的上升子序列的结尾数字 最小是多少 初始f[0]=-inf,f[i]=inf(inf为无穷大,可取值 为大于任意ai绝对值的一个数字)
决斗
把环复制一份,接到环后面,这样编号为x 的人能胜出的充要条件是他能与自己 “相遇”。 123456 1对应4,2对应5,3对应6 由于2可以胜3,因此2将3淘汰后,2和4会 相遇,又因为1可以胜2,因此1将2淘汰后, 1和4会相遇,所以1可能赢得这场决斗。
内存碎片
f[i,j]=min{ f[k,j-1]+ (c[k+1]+c[k+2]+...+c[i])*L[i],0<=k<i} 预处理sc[i]=c[1]+c[2]+...+c[i] f[i,j]=min{ f[k,j-1]+(sc[i]-sc[k])*L[i],0<=k<i)} 时间复杂度O(N^2*K)
方案: 两个11,一个20
内存碎片
算法:动态规划 先将所有L[i]排序。 112344678 222446688 113366688 233377778
这一行是内存申请的长度
这三行是内存分配的可能长度
内存碎片
一种内存长度覆盖的区间必定是连续的, 并且该内存长度等于覆盖区间最后一个内 存申请操作的长度。 令f[i,j]表示考虑完前i个内存申请操作,并且 已经使用完j种内存长度的最少需要的内存。
常见动态规划题目详解
常见动态规划题⽬详解1.爬楼梯题⽬描述:假设你正在爬楼梯。
需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。
你有多少种不同的⽅法可以爬到楼顶呢?注意:给定 n 是⼀个正整数。
⽰例 1:输⼊: 2输出: 2解释:有两种⽅法可以爬到楼顶。
1. 1 阶 + 1 阶2. 2 阶⽰例 2:输⼊: 3输出: 3解释:有三种⽅法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶2. 1 阶 + 2 阶3. 2 阶 + 1 阶实现代码:class Solution {public:int climbStairs(int n) {vector<int> a(n);a[0] = 1;a[1] = 2;if(n == 1){return 1;}if(n == 2){return 2;}for(int i = 2; i < n;i++){a[i] = a[i - 1] + a[i - 2];}return a[n - 1];}};2.变态跳台阶题⽬描述:⼀只青蛙⼀次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。
求该青蛙跳上⼀个n级的台阶总共有多少种跳法。
实现代码:class Solution {public:int jumpFloorII(int number) {if(number == 0){return 0;}int total = 1;for(int i = 1; i < number; i++){total *= 2;}return total;}};3.n年后⽜的数量题⽬描述:假设农场中的母⽜每年会产⽣⼀头⼩母⽜,并且永远不会死。
第⼀年农场中只有⼀头成熟的母⽜,第⼆年开始,母⽜开始⽣⼩母⽜,每只⼩母⽜三年之后成熟⼜可以⽣⼩母⽜,给定整数N,求N年后母⽜的数量。
实现代码:class solution{ public: int f(int n){ if(n < 1){ return 0; } if(n == 1|| n== 2||n == 3){ return n; } int res = 3; int pre = 2; int prepre = 1; int tmp1=0; int tmp2 = 0; for(int i = 4;i < n;i++){ tmp1 = res; tmp2 = pre; res = pre + prepre; pre = tmp1; prepre = tmp2; } return res; }};4.矩形覆盖题⽬描述:我们可以⽤2*1的⼩矩形横着或者竖着去覆盖更⼤的矩形。
几个经典的动态规划问题
几个经典的动态规划问题动态规划复习:《便宜的旅行》分析:这个问题很明显是一个动态规划的标准问题。
考虑某一天晚上车队到达了终点,上一次的花销必然是只与早上车队所在的位置有关的。
这样,由于要求从起点到终点最优的方案,所以从起点到达早上所出发时旅馆的方案也应该是最优的。
以此类推,我们可以得出我们应该求出从起点到各个旅馆的最优方案。
这样,如果我们设从起点到旅馆s i∈S (1≤ i≤ n)的最优方案的价值为f(s i),就可以得到如下的动态规划方程:F(s[i])=min{f(s[j])}+value[i];0<=s[i]-s[j]<=800这里value(s i)为s i的价值。
《蛙人》设F(i,j) 是携带i升氧气,j升氮气的最小重量F(i+a k,j+t k)=min{f(i,j)+W k}李曙华同学程序for i:=0 to 21 dofor j:=0 to 79 doa[i,j]:=10000000;a[0,0]:=0;for i:=1 to n dobeginreadln(b[i,1],b[i,2],b[i,3]);for j:=21-b[i,1] downto 0 dofor k:=79-b[i,2] downto 0 dobeginif a[j,k]>a[j,k+1] then a[j,k]:=a[j,k+1];if a[j,k]>a[j+1,k] then a[j,k]:=a[j+1,k];if a[j+b[i,1],k+b[i,2]]>a[j,k]+b[i,3] thena[j+b[i,1],k+b[i,2]]:=a[j,k]+b[i,3];end;end;writeln(a[x,y]);close(input);close(output);end.几个经典的动态规划问题一、背包问题:在M件物品取出若干件放在空间为W的背包里,每件物品的重量为W1,W·2……Wn,与之相对应的价值为P1,P2……Pn。
动态规划题目分析共23页文档
动态规划题目分析
1、战鼓一响,法律无声。——英国 2、任何法律的根本;不,不成文法本 身就是 讲道理 ……法 律,也 ----即 明示道 理。— —爱·科 克
3、法律是最保险的头盔。——爱·科 克 4、一个国家如果纲纪不正,其国风一 定颓败 。—— 塞内加 5、法律不能使人人平等,但是在法律 面前人 人是平 等的。 ——波 洛克
谢谢你的阅读
❖ 知识就是财富 ❖ 丰富你的人生
71、既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。——康德 72、家庭成为快乐的种子在外也不致成为障碍物但在旅行之际却是夜间的。——伏尔泰 74、路漫漫其修道远,吾将上下而求索。——屈原 75、内外相应,言行相称。——韩非
动态规划实例详解
算法1:递归
#include <iostream.h> #include <string.h> #define MAX 1000 char str1[MAX], str2[MAX]; int commonstr(int,int); void main(){ while(cin>> str1 >> str2){ intlen1=strlen(str1); intlen2=strlen(str2); cout<<commonstr(len1-1,len2-1); cout<<endl; } }
• 动态规划的实质就是
动规的要诀-状态
• 用动态规划解题,关键是要找出“状态”, 和在“状态”间进行转移的办法(即状态 转移方程) • 我们一般在动规的时候所用到的一些数组, 也就是用来存储每个状态的最优值的。
动态规划
• 例2 POJ 1163 数字三角形
7
3 8 1 7 5 2 4 6 8 0 4 5
– 基本思想:将原问题分解为相似的子问题,在 求解的过程中通过子问题的解求出原问题的解 (注意:不是简单分而治之)。 – 只能应用于有最优子结构的问题(即局部最优 解能决定全局最优解,或问题能分解成子问题 来求解)。 – 计算机科学与工程、管理科学(运筹学)等领 域中许多算法的基础,如最短路径、背包问题、 项目管理、网络流优化等。
– 情况一:str1[len1-1] == str2[len1-1],则 f(str1,len1,str2,len2) = 1+ f(str1,len11,str2,len2-1) – 情况二:str1[len1-1] != str2[len1-1],则 f(str1,len1,str2,len2) = max(f(str1,len11,str2,len2), f(str1,len1,str2,len2-1)) – 程序如下:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
跳舞机
• DDR的主要内容是用脚来踩 踏板。踏板有4个方向的箭 头,用1,2,3,4来代表 • 每首歌曲有一个箭头序列, 游戏者必须按照这个序列依 次用某一只脚踩相应的踏板。 在任何时候,两只脚都不能 在同一个踏板上,但可以同 时待在中心位置0。
跳舞机
• 每一个时刻,必须移动而且只能移动一只 脚去踩相应的箭头,另一只脚不许移动。 • 跳DDR会消耗体力。从中心移动到任何一 个箭头耗费2单位体力,从任何一个箭头移 动到相邻箭头耗费3单位体力,移动到相对 的箭头(1和3相对,2和4相对)耗费4单位 体力,而留在原地再踩一下只需要1单位。 • 给定一首舞曲, 每个箭头应该用哪只脚踩才 能使体力消耗最少呢?例如对于序列LLUR, 用LLRR脚去踩,总的体力耗费为2 + 1 + 2 + 3 = 8单位
分析
• 模型:在一个2×N的矩阵中,找出K个子矩 阵。矩阵的每个元素有两个值V和F。题目 要让K个子矩阵的V值和其他矩阵的F值之和 最小,而如果我们令W=V-F,则目标转换 为让K个子矩阵元素的W值之和最小 • 矩阵可以重叠,这给解题带来不便。我们 可以不考虑重叠情况,如图所示
L L
R S(1,2,2,4) S’(1,3,1,6) S(1,2,2,4) S’(1,5,1,6) 图 1-43 重叠情况转化为不重叠情况
决斗
• 编号为1~n的n个人按逆时针方向排成一圈, 他们要决斗n-1场。每场比赛在某相邻两人 间进行,败者退出圈子,紧靠败者右边的 人成为与胜者直接相邻的人。 • 任意两人之间决斗的胜负都将在一矩阵中 给出(如果A[i,j]=1则i与j决斗i总是赢,如果 A[i,j]=0则i与j决斗时i总是输), • 求出所有可能赢得整场决斗的人的序号
索引
• • • • • • • • 【UVAxxx】最长上升子序列问题 【UVAxxx】最优二分检索树问题 【POJ1180】任务调度问题 【AOA】序列分割问题 【AOA】多排列的LCS 【POJ1159】回文词 【AOA】友好城市 【POJ1160】邮局
索引
• • • • • 【AOA】基因串 【POJ1946】奶牛转圈 【AOA】元件折叠 【AOA】 DNA序列 【AOA】最优布车方案
《算法艺术与信息学竞赛》 45道动态规划题目
刘汝佳
索引
• • • • • • • • 【POJ1141】括号序列 【POJ1191】棋盘分割 【SPOJ196】决斗 【AOA】跳舞机 【AOA】积木游戏 【AOA】艺术馆的火灾 【AOA】机器人的名字 【UVa10559】方块消除
索引
• • • • • • • • 【AOA】公路巡逻 【POJ1074】并行期望值 【AOA】高性能计算机 【AOA】模板匹配 【AOA】不可解码的编码 【AOA】青蛙的烦恼 【AOA】排列问题 【AOA】最优排序二叉树
– g: 本来是三维的O(L3)的, 但注意到在每个式子 里b参量没有发生变化, 故以b为阶段递推, 只需 要O(L2)的空间 – 预处理结果: 如果用h[a,b,c]表示是否有S[a, a+c-1]=S[b, b+c-1], 则又是三维的. 可以用链式 存储, 用next[a,b]表示子串S[a,b]的下一个相同 子串的开始位置, 则只需要O(L2)的空间
– (, [, ], )(, ([()
• 现在,给出一些由‘(’,‘)’,‘[’,‘]’构成的序 列,请添加尽量少的括号,得到一个规则序列。
分析
• d[i,j]: 子串i…j最少需要添加的括号数 • 状态转移
– S形如(S’)或者[S’]: d[i+1,j-1] – S形如(S’或者[S’: d[i+1,j]+1 – S形如S’)或者S’]: d[i,j-1]+1 – 长度大于1: d[i,k]+d[k+1,j] (i<=k<=j-1)
• 状态O(kn2)个, 决策O(n), 转移时间O(1)(先预处理), 总时间O(kn3)
机器人的名字
• 考虑一种基于重复子串的压缩方法 • 用[St]k表示k个相同的子串St(其中St称为重复子串, k是一个单字节整数,只占一个字符位置) • 如果这k个子串并没有连在一起,则可以在[St]k的 后面加上{S1}t1{S2} t2…{Sr} tr(1<ti<k,ti<ti+1), 表示在第ti个St的后面放置Si,Si称为插入子串 • St和Si也都可以是压缩后的字符串 • 比如I_am_WhatWhat_is_WhatWhat的压缩结果 为I_am_[What]4{_is_}2,长度为19 (例子中的空 格用下划线“_”表示,数字2和4实际上是用单字 节二进制表示的) • 名字不会以空格开始或结尾,大小写敏感
索引
• • • • • • • • 【POJ1038】 Bugs公司 【UVa10531】迷宫统计 【AOA】贪吃的九头龙 【AOA】快乐的蜜月 【AOA】移动机器人 【UVa10271】佳佳的筷子 【AOA】偷懒的工人 【AOA】铁路调度
索引
• • • • • • • • 【POJ1691】平板涂色 【POJ1947】道路重建 【ZJUxxx】圆和多边形 【AOA】铁球落地 【UVA10118】免费糖果 【AOA】丢三落四的老鼠 【AOA】最长公共子序列问题 【UVA10635】排列的LCS问题
• 原棋盘上每一格有一个分值,一块矩形棋 盘的总分为其所含各格分值之和。现在需 要把棋盘按上述规则分割成n块矩形棋盘, 并使各矩形棋盘总分的均方差最小。
(a) 允许的分割方案
(b) 不允许的分割方案
分析
• 变形均方差公式
n n 1 1 n 2 2 ( n( x ) 2 x i 2 2 x x i ) x i ( x ) 2 n n i 1 i 1 i 1
• 平均值是一定的(等于所有方格里的数的 和除以n) • 只需要让每个矩形总分的平方和尽量小
分析
• 考虑左上角坐标为(x1,y1),右下角坐标为 (x2,y2)的棋盘,设它把切割k次以后得到的 k+1块矩形的总分平方和最小值为 d[k,x1,y1,x2,y2] • 状态转移: 沿着某横线切或者竖线切,然后 选一块继续切, 如横着切的两类决策是
• 状态O(n2), 转移O(n), 共(n3)
ቤተ መጻሕፍቲ ባይዱ
棋盘分割
• 将一个8×8的棋盘进行如图所示的分割: 将原棋盘割下一块矩形棋盘并使剩下部分 也是矩形,再将剩下的部分继续如此分割, 这样割了(n-1)次后,连同最后剩下的矩形 棋盘共有n(n<15)块矩形棋盘(每次切割 都只能沿着棋盘格子的边进行)。
棋盘分割
括号序列
• 定义如下规则序列(字符串):
– 空序列是规则序列; – 如果S是规则序列,那么(S)和[S]也是规则序列; – 如果A和B都是规则序列,那么AB也是规则序列。
• 例如,下面的字符串都是规则序列:
– (), [], (()), ([]), ()[], ()[()]
• 这几个则不是规则序列:
积木游戏
• 有N块编号依次为1,2,…,N的长方体积木。每 块积木有三条不同边分别称为a、b、c边
a c
b
• 从积木中选出若干块分成M堆, 每堆至少有1块积 木,并且第K堆中任意一块积木的编号要大于第 K+1堆中任意一块积木的编号
积木游戏
• 每一堆积木要垂直摞成一根柱子,并满足
– 除最顶上的一块积木外,任意一块积木的上表 面同且仅同另一块积木的下表面接触,并且要 求下面积木的上表面能包含上面的积木的下表 面,也就是说,要求下面积木的上表面两对边 的长度分别大于等于上面积木两对边的长度。 – 对于任意两块上下表面相接触的积木,下面积 木的编号要小于上面积木的编号
分析
• 边界条件
g[a, b, c] d [ a , b ] 3 b a 1 2 c b a 1 或者 S[a, a c 1] S[b c 1, b] c b a 1
• d[a,b]的状态转移方程
分析
• g[a,b,c]表示将串S[a,b], 选择长度为c的重复 子串进行压缩得到的最短长度. 枚举插入串 (可能为空)的下一个位置i, 状态转移方程为
g[i, b, c] i a c g[a, b, c] min a c i b c 1 g[i, b, c] d[a c, i 1] 3 i a c S [ a ,a c 1] S [i ,i c 1]
分析
• 令d[a,b]表示以a, b为起止位置的串(记为 S[a,b])的最短压缩长度, 则目标为d[1,L] • 状态转移
– 连接: d[a,b] = min{d[a,i] + d[i+1,b]}, a<=i<b – 压缩: 需要确定重复子串. 当重复子串很多时, 决策枚举的代价较大
• 压缩决策可以通过动态规划来枚举!
min{d[a, i] d[i 1, b]} a i b d[a, b] min 1min1{g[a, b, i]} i b a
• 如何较快的判断是否有S[a, a+c-1]=S[i, i+c-1]? 从c=1开始递推, 总O(L3)
分析
• 时间: 预处理O(L3), 核心O(L4), 共O(L4) • 空间
• 状态O(n2m)个, 决策O(1), 总时间O(n2m)
艺术馆的火灾
• 艺术馆着火了. 这是一幢两层的小楼,每层有N个 房间,用两个数分别表示艺术品价值和火势.
40/50 30/40 50/40 30/50 30/50 40/20 60/70 20/30
• 灭火器最多只能发射K次,每次发射将覆盖一个 矩形的区域(矩形的高度可以是1也可以是2), 所到之处不但火焰会被扑灭,艺术品也被摧毁。 • 你需要决定灭火器每次应该怎样发射,才能将这 次火灾的损失降到最低限度。损失等于摧毁的艺 术品总价值加上剩余的火势总值