动态规划问题整理
动态规划资源分配问题
S1
7
X1
12
3
4
P1(x1)
44
5
8
F2+ p1 21 19
17 18
f1(s1)
21
X1*
1
• 当k=2时;
f2(s2) = max [p2(x2)+ f3(s3) ]
1< x2 < s2 3< s2< 6 计算结果:
S2 X2 p2(x2) F3+ p2 f2(s2) X2*
34 1 12 3 35 10 12 12 10 12 1 1或2
f(k* sk ) max{ fk (sk , xk )}
xk 1,2,3...,sk
4
xi sk
ik
xi大于等于1且为整数
将递推关系写出即是
f
* k
(
sk
)
xk
max
1, 2 ,..., sk
{Pk
(
xk
)
f
* k 1
(
sk
xk )}
f(5* s5)=0
k 1,2,3
当k=4时;
f4(s4) = max [p4(x4)]
S3 X3 p3(x3) F3+ p3 f3(s3) X3*
23 1 12 5 56 7 98 79 11
4 123 568 12 10 10 12 1
5 1 2 34 5 6 88 13 13 12 10 13 1或2
• 当k=1时;
f1(s1) = max [p1(x1)+ f2(s2) ]
1< x1< s1 s1=7 计算结果:
5 123 35 6 15 14 13 15 1
动态规划47题
动态规划练习【题目一览】总分【问题描述】学生在我们USACO的竞赛中的得分越多我们越高兴。
我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助。
我们可以从几个种类中选取竞赛的题目,这里的一个“种类”是指一个竞赛题目的集合,解决集合中的题目需要相同多的时间并且能得到相同的分数。
你的任务是写一个程序来告诉USACO的职员,应该从每一个种类中选取多少题目,使得解决题目的总耗时在竞赛规定的时间里并且总分最大。
输入包括竞赛的时间M(1<=M<=10000)(不要担心,你要到了训练营中才会有长时间的比赛)和“种类”的数目N(1<=N<=10000)。
后面的每一行将包括两个整数来描述一个“种类”:第一个整数说明解决这种题目能得的分数(1<=points<=10000),第二整数说明解决这种题目所需的时间(1<=minutes<=10000)。
你的程序应该确定我们应该从每个“种类”中选多少道题目使得能在竞赛的时间中得到最大的分数。
来自任意的“种类”的题目数目可能任何非负数(0或更多)。
计算可能得到的最大分数。
【输入格式】输入文件中的第1行:M,N--竞赛的时间和题目“种类”的数目。
第2~N+1行:两个整数:每个“种类”题目的分数和耗时。
【输出格式】输出文件中仅一行,包括那个在给定的限制里可能得到的最大的分数。
【输入输出样例】输入:300 4100 60250 120120 10035 20输出:605从第2个“种类”中选两题第4个“种类”中选三题。
邮票【问题描述】已知一个N枚邮票的面值集合(如,{1分,3分})和一个上限K——表示信封上能够贴K张邮票。
计算从1到M的最大连续可贴出的邮资。
例如,假设有1分和3分的邮票;你最多可以贴5张邮票。
很容易贴出1到5分的邮资(用1分邮票贴就行了),接下来的邮资也不难:6 = 3 + 37 = 3 + 3 + 18 = 3 + 3 + 1 + 19 = 3 + 3 + 310 = 3 + 3 + 3 + 111 = 3 + 3 + 3 + 1 + 112 = 3 + 3 + 3 + 313 = 3 + 3 + 3 + 3 + 1然而,使用5枚1分或者3分的邮票根本不可能贴出14分的邮资。
动态规划算法详解及经典例题
动态规划算法详解及经典例题⼀、基本概念(1)⼀种使⽤多阶段决策过程最优的通⽤⽅法。
(2)动态规划过程是:每次决策依赖于当前状态,⼜随即引起状态的转移。
⼀个决策序列就是在变化的状态中产⽣出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
假设问题是由交叠的⼦问题所构成,我们就能够⽤动态规划技术来解决它。
⼀般来说,这种⼦问题出⾃对给定问题求解的递推关系中,这个递推关系包括了同样问题的更⼩⼦问题的解。
动态规划法建议,与其对交叠⼦问题⼀次重新的求解,不如把每⼀个较⼩⼦问题仅仅求解⼀次并把结果记录在表中(动态规划也是空间换时间的)。
这样就能够从表中得到原始问题的解。
(3)动态规划经常常使⽤于解决最优化问题,这些问题多表现为多阶段决策。
关于多阶段决策:在实际中,⼈们经常遇到这样⼀类决策问题,即因为过程的特殊性,能够将决策的全过程根据时间或空间划分若⼲个联系的阶段。
⽽在各阶段中。
⼈们都须要作出⽅案的选择。
我们称之为决策。
⽽且当⼀个阶段的决策之后,经常影响到下⼀个阶段的决策,从⽽影响整个过程的活动。
这样,各个阶段所确定的决策就构成⼀个决策序列,常称之为策略。
因为各个阶段可供选择的决策往往不⽌⼀个。
因⽽就可能有很多决策以供选择,这些可供选择的策略构成⼀个集合,我们称之为同意策略集合(简称策略集合)。
每⼀个策略都对应地确定⼀种活动的效果。
我们假定这个效果能够⽤数量来衡量。
因为不同的策略经常导致不同的效果,因此,怎样在同意策略集合中选择⼀个策略,使其在预定的标准下达到最好的效果。
经常是⼈们所关⼼的问题。
我们称这种策略为最优策略,这类问题就称为多阶段决策问题。
(4)多阶段决策问题举例:机器负荷分配问题某种机器能够在⾼低两种不同的负荷下进⾏⽣产。
在⾼负荷下⽣产时。
产品的年产量g和投⼊⽣产的机器数量x的关系为g=g(x),这时的年完善率为a,即假设年初完善机器数为x,到年终时完善的机器数为a*x(0<a<1);在低负荷下⽣产时,产品的年产量h和投⼊⽣产的机器数量y 的关系为h=h(y)。
动态规划例题
动态规划例题动态规划是一种以最优化原理为基础的问题求解方法,通过拆分问题为若干阶段,每个阶段求解一个子问题,再逐步推导出整个问题的最优解。
例如,有一个背包能够承受一定的重量,现有一些物品,每个物品都有自己的重量和价值。
我们希望将物品放入背包中,使得背包的总价值最大。
这个问题可以用动态规划来解决。
首先,我们定义一个二维数组dp,其中dp[i][j]表示在前i个物品中,容量为j的背包中所能放入的物品的最大价值。
那么,对于每一个物品,可以选择放入背包或者不放入背包。
如果选择放入背包,最大价值为dp[i-1][j-w[i]] + v[i],其中w[i]表示第i个物品的重量,v[i]表示第i个物品的价值。
如果选择不放入背包,最大价值为dp[i-1][j]。
因此,dp[i][j]的状态转移方程为:dp[i][j] = max(dp[i-1][j-w[i]] + v[i], dp[i-1][j])。
基于这个状态转移方程,可以逐步求解从第1个物品到第n个物品的最大价值。
最终,dp[n][W]即为问题的最优解,其中W 表示背包的容量。
举个简单的例子,假设背包的容量为10,有3个物品,它们的重量分别为3、4、5,价值分别为4、5、6。
此时,可以得到如下的dp矩阵:0 0 0 0 0 0 0 0 0 0 00 0 0 4 4 4 4 4 4 4 40 0 0 4 5 5 9 9 9 9 90 0 0 4 5 5 9 10 10 14 14我们可以看到,dp[3][10]的最大价值为14,表示在前3个物品中,容量为10的背包中所能放入的物品的最大价值为14。
通过动态规划,我们可以有效地求解背包问题,得到物品放入背包的最优解。
这个例子只是动态规划的一个简单应用,实际上,动态规划可以解决各种复杂的问题,如最长公共子序列、最大子数组和、最大字段和等。
因此,学习动态规划是非常有意义的。
动态规划问题常见解法
动态规划问题常见解法
动态规划是一种高效解决优化问题的方法。
它通常用于涉及最
优化问题和最短路径的计算中。
下面是一些常见的动态规划问题解法:
1. 背包问题
背包问题是动态规划中的经典问题之一。
其目标是在给定的背
包容量下,选择一些物品放入背包中,使得物品总价值最大。
解决
这个问题的常见方法是使用动态规划的思想,定义一个二维数组来
记录每个物品放入背包时的最大价值,然后逐步计算出最终的结果。
2. 最长公共子序列问题
最长公共子序列问题是寻找两个字符串中最长的公共子序列的
问题。
解决这个问题的常见方法是使用动态规划的思想,定义一个
二维数组来记录两个字符串中每个位置的最长公共子序列的长度。
然后通过递推关系来计算出最终的结果。
3. 矩阵链乘法问题
矩阵链乘法问题是计算一系列矩阵相乘的最佳顺序的问题。
解
决这个问题的常见方法是使用动态规划的思想,定义一个二维数组
来记录每个矩阵相乘时的最小乘法次数,然后逐步计算出最终的结果。
4. 最长递增子序列问题
最长递增子序列问题是寻找一个序列中最长的递增子序列的问题。
解决这个问题的常见方法是使用动态规划的思想,定义一个一
维数组来记录每个位置处的最长递增子序列的长度,然后通过递推
关系来计算出最终的结果。
以上是一些常见的动态规划问题解法。
通过灵活运用这些方法,我们可以更高效地解决优化问题和最短路径计算等相关任务。
动态规划习题完整版
动态规划习题Document serial number【NL89WT-NY98YT-NC8CB-NNUUT-NUT108】动态规划专题分类视图数轴动规题:题1.2001年普及组第4题--装箱问题【问题描述】有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0<n≤30),每个物品有一个体积(正整数)。
要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
【输入格式】输入文件box.in有若干行。
第一行:一个整数,表示箱子容量V;第二行:一个整数,表示物品个数n;接下来n行,分别表示这n个物品的各自体积。
【输出格式】输出文件box.out只有一行数据,该行只有一个数,表示最小的箱子剩余空间。
【输入样例】2468312797【输出样例】题2.1996年提高组第4题--砝码秤重__数据加强版【问题描述】设有n种砝码,第k种砝码有Ck 个,每个重量均为Wk,求:用这些砝码能秤出的不同重量的个数,但不包括一个砝码也不用的情况。
【输入格式】输入文件weight.in的第一行只有一个数n,表示不同的砝码的种类数.第2行至第n+1行,每行有两个整数.第k+1行的两个数分别表示第k种砝码的个数和重量.【输出格式】输出文件weight.out中只有一行数据:Total=N。
表示用这些砝码能秤出的不同重量数。
【输入样例】22223【输出样例】Total=8【样例说明】重量2,3,4,5,6,7,8,10都能秤得【数据限制】对于100%的数据,砝码的种类n满足:1≤n≤100;对于30%的数据,砝码的总数量C满足:1≤C≤20;对于100%的数据,砝码的总数量C满足:1≤C≤100;对于所有的数据,砝码的总重量W满足:1≤W≤400000;题3.石子归并-szgb.pas【问题描述】有一堆石头质量分别为W1,W2,…,Wn.(Wi≤10000),将石头合并为两堆,使两堆质量的差最小。
【输入】输入文件szgb.in的第一行只有一个整数n(1≤n≤50),表示有n堆石子。
动态规划总结经典题目(经典中的经典)
动态规划总结——经典问题总结本文着重讨论状态是如何表示,以及方程是怎样表示的。
当然,还附上关键的,有可能作为模板的代码段。
但有的代码的实现是优化版的。
经典问题总结最长上升子序列(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,求它们的最长、连续的公共字串。
动态规划和几个经典问题
动态规划和⼏个经典问题动态规划 (本⽂适合⼊门理解思想,后期多刷题) 动态规划是运筹学的⼀个分⽀,是求解多阶段决策过程最优化问题的数学⽅法,在经济管理、⼯程技术、⼯农业⽣产及军事部门中都有着⼴泛的应⽤,并且获得了显著的效果。
学习动态规划,我们⾸先要了解多阶段决策问题。
多阶段决策问题例⼦: ⽣产决策问题:企业在⽣产过程中,由于需求是随时间变化的,因此企业为了获得全年的最佳⽣产效益,就要在整个⽣产过程中逐⽉或逐季度地根据库存和需求决定⽣产计划。
机器负荷分配问题:某种机器可以在⾼低两种不同的负荷下进⾏⽣产。
要求制定⼀个五年计划,在每年开始时,决定如何重新分配完好的机器在两种不同的负荷下⽣产的数量,使在五年内产品的总产量达到最⾼。
航天飞机飞⾏控制问题:由于航天飞机的运动的环境是不断变化的,因此就要根据航天飞机飞⾏在不同环境中的情况,不断地决定航天飞机的飞⾏⽅向和速度(状态),使之能最省燃料和完成飞⾏任务(如软着陆)。
多阶段决策过程的特点: 根据过程的特性可以将过程按空间、时间等标志分为若⼲个互相联系⼜互相区别的阶段。
在每⼀个阶段都需要做出决策,从⽽使整个过程达到最好的效果。
各个阶段决策的选取不是任意确定的,它依赖于当前⾯临的状态,⼜影响以后的发展。
当各个阶段的决策确定后,就组成了⼀个决策序列,因⽽也就决定了整个过程的⼀条活动路线,这样的⼀个前后关联具有链状结构的多阶段过程就称为多阶段决策问题。
针对多阶段决策过程的最优化问题,美国数学家Bellman等⼈在20世纪50年代初提出了著名的最优化原理,把多阶段决策问题转化为⼀系列单阶段最优化问题,从⽽逐个求解,创⽴了解决这类过程优化问题的新⽅法:动态规划。
对最佳路径(最佳决策过程)所经过的各个阶段,其中每个阶段始点到全过程终点的路径,必定是该阶段始点到全过程终点的⼀切可能路径中的最佳路径(最优决策),这就是Bellman提出的著名的最优化原理。
动态规划习题
动态规划专题分类视图数轴动规题: (1)较复杂的数轴动规 (4)线性动规 (7)区域动规: (14)未知的动规: (20)数轴动规题:题1.2001年普及组第4题--装箱问题【问题描述】有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0<n≤30),每个物品有一个体积(正整数)。
要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
【输入格式】输入文件box.in有若干行。
第一行:一个整数,表示箱子容量V;第二行:一个整数,表示物品个数n;接下来n行,分别表示这n个物品的各自体积。
【输出格式】输出文件box.out只有一行数据,该行只有一个数,表示最小的箱子剩余空间。
【输入样例】2468312797【输出样例】题2.1996年提高组第4题--砝码秤重__数据加强版【问题描述】设有n种砝码,第k种砝码有C k个,每个重量均为W k,求:用这些砝码能秤出的不同重量的个数,但不包括一个砝码也不用的情况。
【输入格式】输入文件weight.in的第一行只有一个数n,表示不同的砝码的种类数.第2行至第n+1行,每行有两个整数.第k+1行的两个数分别表示第k种砝码的个数和重量.【输出格式】输出文件weight.out中只有一行数据:Total=N。
表示用这些砝码能秤出的不同重量数。
【输入样例】22 22 3【输出样例】Total=8【样例说明】重量2,3,4,5,6,7,8,10都能秤得【数据限制】对于100%的数据,砝码的种类n满足:1≤n≤100;对于30%的数据,砝码的总数量C满足:1≤C≤20;对于100%的数据,砝码的总数量C满足:1≤C≤100;对于所有的数据,砝码的总重量W满足:1≤W≤400000;题3.石子归并-szgb.pas【问题描述】有一堆石头质量分别为W1,W2,…,Wn.(Wi≤10000),将石头合并为两堆,使两堆质量的差最小。
【输入】输入文件szgb.in的第一行只有一个整数n(1≤n≤50),表示有n堆石子。
(完整版)动态规划问题常见解法
(完整版)动态规划问题常见解法动态规划问题常见解法一、背包问题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>
动态规划问题常见解法
动态规划问题常见解法动态规划(Dynamic Programming)是一种常用的算法思想,用于解决一类具有重叠子问题性质和最优子结构性质的问题。
动态规划通常通过将问题划分为若干个子问题,并分别求解子问题的最优解,从而得到原问题的最优解。
以下是动态规划问题常见的解法:1. 斐波那契数列斐波那契数列是动态规划问题中的经典案例。
它的递推关系式为 F(n) = F(n-1) + F(n-2),其中 F(0) = 0,F(1) = 1。
可以使用动态规划的思想来解决斐波那契数列问题,通过保存已经计算过的子问题的结果,避免重复计算。
2. 背包问题背包问题是一个经典的优化问题,可以使用动态规划的方法进行求解。
背包问题包括 0/1 背包问题和完全背包问题。
0/1 背包问题中每个物品要么被选中放入背包,要么不选。
完全背包问题中每个物品可以被选中多次放入背包。
通过定义状态转移方程和使用动态规划的思想,可以高效地求解背包问题。
3. 最长递增子序列最长递增子序列是一个常见的子序列问题,可以使用动态规划的方法进行求解。
最长递增子序列指的是在一个序列中,找到一个最长的子序列,使得子序列中的元素按照顺序递增。
通过定义状态转移方程和使用动态规划的思想,可以有效地求解最长递增子序列问题。
4. 最长公共子序列最长公共子序列是一个经典的字符串问题,可以使用动态规划的方法进行求解。
给定两个字符串,找到它们之间最长的公共子序列。
通过定义状态转移方程和使用动态规划的思想,可以高效地求解最长公共子序列问题。
5. 矩阵链乘法矩阵链乘法是一个求解最优括号化问题的经典案例,可以使用动态规划的方法进行求解。
给定多个矩阵的大小,需要找到一个最优的计算顺序,使得计算乘积的次数最少。
通过定义状态转移方程和使用动态规划的思想,可以高效地求解矩阵链乘法问题。
以上是动态规划问题的常见解法,通过使用动态规划的思想和方法,可以解决这些问题,并求得最优解。
常见动态规划题目详解
常见动态规划题⽬详解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的⼩矩形横着或者竖着去覆盖更⼤的矩形。
动态规划资源分配问题
小组成员:黄秀梅 罗燕雯 杨俊 李彩霞 林琳 (女) 吴晶莹 邓桂兰 罗碧辉
可编辑ppt
1
资源分配问题:只有一种资源有待于分配到 若干个活动,其目标是如何最有效地在各 个活动中分配这种资源。在建立任何效益 分配问题的DP(Dynamic Programming )模型 时,阶段对应于活动,每个阶段的决策对 应于分配到该活动的资源数量;任何状态 的当前状态总是等于留待当前阶段和以后 阶段分配的资源数量,即总资源量减去前 面各阶段已分配的资源量。
可编辑ppt
3
课程 1 学分 复习天数
234
1
4 35 2
2
54 5 6
3
4
4
5 68 7
8 7 88
可编辑ppt
4
解:这个问题要求作出4个相应关联的决策,即应分配多 少天给每门考试科目。因此,即使这里没有固定的次序, 这四门考试科目可以看成动态规划模型中的四个阶段。 阶段:k=1,2,3,4。考试科目 决策变量:x(k k=1,2,3,4)是分配到阶段(考试科目) k的天数; 状态变量:sk是仍待分配的天数(即前面阶段未分配完的天数)
4
f(k
s
,
k
x
)=
k
P(k
x
)+
k
max
{
Pi ( x i )}
ik 1
f
பைடு நூலகம்
(*
k
sk
)
max{
f k ( s k , x k )}
x k 1,2 ,3 ..., s k
4
xi sk
ik
x i大于等于 1且为整数
将递推关系写出即是
100个动态规划方程
100个动规方程 1. 资源问题1-----机器分配问题 F[I,j]:=max(f[i-1,k]+w[i,j-k]) 2. 资源问题2------01背包问题 F[I,j]:=max(f[i-1,j-v]+w,f[i-1,j]); 3. 线性动态规划1-----朴素最长非降子序列 F:=max{f[j]+1} 4. 剖分问题1-----石子合并 F[i,j]:=min(f[i,k]+f[k+1,j]+sum[i,j]); 5. 剖分问题2-----多边形剖分 F[I,j]:=min(f[i,k]+f[k,j]+a[k]*a[j]*a); 6. 剖分问题3------乘积最大 f[i,j]:=max(f[k,j-1]*mult[k,i]); 7. 资源问题3-----系统可靠性(完全背包) F[i,j]:=max{f[i-1,j-c*k]*P[I,x]} 8. 贪心的动态规划1-----快餐问题 F[i,j,k]:=max{f[i-1,j',k']+(T-(j-j')*p1-(k-k')*p2) div p3} 9. 贪心的动态规划2----过河 f=min{{f(i-k)} (not stone) {f(i-k)}+1} (stone); +贪心压缩状态 10. 剖分问题4-----多边形-讨论的动态规划 F[i,j]:=max{正正 f[I,k]*f[k+1,j]; 负负 g[I,k]*f[k+1,j]; 正负 g[I,k]*f[k+1,j]; 负正 f[I,k]*g[k+1,j];} g 为min 11. 树型动态规划1-----加分二叉树 (从两侧到根结点模型) F[I,j]:=max{f[I,k-1]*f[k+1,j]+c[k]} 12. 树型动态规划2-----选课 (多叉树转二叉树,自顶向下模型) F[I,j]表示以i 为根节点选j 门功课得到的最大学分 f[i,j]:=max{f[t.l,k]+f[t.r,j-k-1]+c} 13. 计数问题1-----砝码称重 f[f[0]+1]=f[j]+k*w[j]; (1<=i<=n; 1<=j<=f[0]; 1<=k<=a;)14. 递推天地1------核电站问题 f[-1]:=1; f[0]:=1; f:=2*f[i-1]-f[i-1-m] 15. 递推天地2------数的划分 f[i,j]:=f[i-j,j]+f[i-1,j-1]; 16. 最大子矩阵1-----一最大01子矩阵 f[i,j]:=min(f[i-1,j],v[i,j-1],v[i-1,j-1])+1; ans:=maxvalue(f); 17. 判定性问题1-----能否被4整除 g[1,0]:=true; g[1,1]:=false; g[1,2]:=false; g[1,3]:=false; g[i,j]:=g[i-1,k] and ((k+a[i,p]) mod 4 = j) 18. 判定性问题2-----能否被k 整除 f[I,j±n mod k]:=f[i-1,j]; -k<=j<=k; 1<=i<=n 20. 线型动态规划2-----方块消除游戏 f[i,i-1,0]:=0 f[i,j,k]:=max{f[i,j-1,0]+sqr(len(j)+k), f[i,p,k+len[j]]+f[p+1,j-1,0]} ans:=f[1,m,0] 21. 线型动态规划3-----最长公共子串,LCS 问题 f[i,j]={0(i=0)&(j=0); f[i-1,j-1]+1 (i>0,j>0,x=y[j]); max{f[i,j-1]+f[i-1,j]}} (i>0,j>0,x<>y[j]); 22. 最大子矩阵2-----最大带权01子矩阵O(n^2*m) 枚举行的起始,压缩进数列,求最大字段和,遇0则清零 23. 资源问题4-----装箱问题(判定性01背包) f[j]:=(f[j] or f[j-v]);24. 数字三角形1-----朴素の数字三角形 f[i,j]:=max(f[i+1,j]+a[I,j],f[i+1,j+1]+a[i,j]);25. 数字三角形2-----晴天小猪历险记之Hill 同一阶段上暴力动态规划if[i,j]:=min(f[i,j-1],f[I,j+1],f[i-1,j],f[i-1,j-1])+a[i,j] 26. 双向动态规划1数字三角形3 -----小胖办证 f[i,j]:=max(f[i-1,j]+a[i,j],f[i,j-1]+a[i,j],f[i,j+1]+a[i,j])27. 数字三角形4-----过河卒 //边界初始化 f[i,j]:=f[i-1,j]+f[i,j-1]; 28. 数字三角形5-----朴素的打砖块 f[i,j,k]:=max(f[i-1,j-k,p]+sum[i,k],f[i,j,k]); 29. 数字三角形6-----优化的打砖块 f[I,j,k]:=max{g[i-1,j-k,k-1]+sum[I,k]} 30. 线性动态规划3-----打鼹鼠’ f:=f[j]+1;(abs(x-x[j])+abs(y-y[j])<=t-t[j]) 31. 树形动态规划3-----贪吃的九头龙 32. 状态压缩动态规划1-----炮兵阵地 Max(f[Q*(r+1)+k],g[j]+num[k]) If (map and plan[k]=0) and ((plan[P] or plan[q]) and plan[k]=0) 33. 递推天地3-----情书抄写员 f:=f[i-1]+k*f[i-2] 34. 递推天地4-----错位排列 f:=(i-1)(f[i-2]+f[i-1]); f[n]:=n*f[n-1]+(-1)^(n-2); 35. 递推天地5-----直线分平面最大区域数 f[n]:=f[n-1]+n :=n*(n+1) div 2 + 1; 36. 递推天地6-----折线分平面最大区域数 f[n]:=(n-1)(2*n-1)+2*n; 37. 递推天地7-----封闭曲线分平面最大区域数 f[n]:=f[n-1]+2*(n-1) :=sqr(n)-n+2; 38 递推天地8-----凸多边形分三角形方法数 f[n]:=C(2*n-2,n-1) div n; 对于k 边形 f[k]:=C(2*k-4,k-2) div (k-1); //(k>=3) 39 递推天地9-----Catalan 数列一般形式 1,1,2,5,14,42,132 f[n]:=C(2k,k) div (k+1);40 递推天地10-----彩灯布置排列组合中的环形染色问题f[n]:=f[n-1]*(m-2)+f[n-2]*(m-1); (f[1]:=m; f[2]:=m(m-1);41 线性动态规划4-----找数线性扫描sum:=f+g[j];(if sum=Aim then getout; if sum<Aim then inc(i) else inc(j);)42 线性动态规划5-----隐形的翅膀min:=min{abs(w/w[j]-gold)};if w/w[j]<gold then inc(i) else inc(j);43 剖分问题5-----最大奖励f:=max(f,f[j]+(sum[j]-sum)*i-t44 最短路1-----Floydf[i,j]:=max(f[i,j],f[i,k]+f[k,j]);ans[q[i,j,k]]:=ans[q[i,j,k]]+s[i,q[i,j,k]]*s[q[i,j,k],j]/s[i,j];45 剖分问题6-----小H的小屋F[l,m,n]:=f[l-x,m-1,n-k]+S(x,k);46 计数问题2-----陨石的秘密(排列组合中的计数问题)Ans[l1,l2,l3,D]:=f[l1+1,l2,l3,D+1]-f[l1+1,l2,l3,D];F[l1,l2,l3,D]:=Sigma(f[o,p,q,d-1]*f[l1-o,l2-p,l3-q,d]);47 线性动态规划------合唱队形两次F:=max{f[j]+1}+枚举中央结点48 资源问题-----明明的预算方案:加花的动态规划f[i,j]:=max(f[i,j],f[l,j-v-v[fb]-v[fa]]+v*p+v[fb]*p[fb]+v[fa]*p[ fa]);49 资源问题-----化工场装箱员50 树形动态规划-----聚会的快乐f[i,2]:=max(f[i,0],f[i,1]);f[i,1]:=sigma(f[t^.son,0]);f[i,0]:=sigma(f[t^.son,3]);51 树形动态规划-----皇宫看守f[i,2]:=max(f[i,0],f[i,1]);f[i,1]:=sigma(f[t^.son,0]); f[i,0]:=sigma(f[t^.son,3]);52 递推天地-----盒子与球f[i,1]:=1;f[i,j]:=j*(f[i-1,j-1]+f[i-1,j]);53 双重动态规划-----有限的基因序列f:=min{f[j]+1}g[c,i,j]:=(g[a,i,j] and g[b,i,j]) or (g[c,i,j])54 最大子矩阵问题-----居住空间f[i,j,k]:=min(min(min(f[i-1,j,k],f[i,j-1,k]),min(f[i,j,k-1],f[i-1,j-1,k])),min(min(f[i-1,j,k-1],f[i,j-1,k-1]),f[i-1,j-1,k-1]))+1;55 线性动态规划------日程安排f:=max{f[j]}+P[I]; (e[j]<s)56 递推天地------组合数C[I,j]:=C[i-1,j]+C[I-1,j-1]C[I,0]:=157 树形动态规划-----有向树k中值问题F[I,r,k]:=max{max{f[l,I,j]+f[r,I,k-j-1]},f[f[l,r,j]+f[r,r,k-j]+w[I,r]]}58 树形动态规划-----CTSC 2001选课F[I,j]:=w(if i∈P)+f[l,k]+f[r,m-k](0≤k≤m)(if l<>0)59 线性动态规划-----多重历史f[i,j]:=sigma{f[i-k,j-1]}(if checked)60 背包问题(+-1背包问题+回溯)-----CEOI1998Substractf[i,j]:=f[i-1,j-a] or f[i-1,j+a]61 线性动态规划(字符串)-----NOI 2000 古城之谜f[i,1,1]:=min{f[i+length(s),2,1],f[i+length(s),1,1]+1}f[i,1,2]:=min{f[i+length(s),1,2]+words[s],f[i+length(s),1,2]+words[s]}62 线性动态规划-----最少单词个数f[i,j]:=max{f[I,j],f[u-1,j-1]+l}63 线型动态规划-----APIO2007 数据备份状态压缩+剪掉每个阶段j前j*2个状态和j*2+200后的状态贪心动态规划f:=min(g[i-2]+s,f[i-1]);64 树形动态规划-----APIO2007 风铃f:=f[l]+f[r]+{1 (if c[l]<c[r])}g:=1(d[l]<>d[r]) 0(d[l]=d[r])g[l]=g[r]=1 then Halt;65 地图动态规划-----NOI 2005 adv19910F[t,i,j]:=max{f[t-1,i-dx[d[[t]],j-dy[d[k]]]+1],f[t-1,i,j];66 地图动态规划-----优化的NOI 2005 adv19910F[k,i,j]:=max{f[k-1,i,p]+1} j-b[k]<=p<=j;67 目标动态规划-----CEOI98 subtraF[I,j]:=f[I-1,j+a] or f[i-1,j-a]68 目标动态规划----- Vijos 1037搭建双塔问题F[value,delta]:=g[value+a,delta+a] or g[value,delta-a]69 树形动态规划-----有线电视网f[i,p]:=max(f[i,p],f[i,p-q]+f[j,q]-map[i,j])leaves>=p>=l, 1<=q<=p;70 地图动态规划-----vijos某题F[I,j]:=min(f[i-1,j-1],f[I,j-1],f[i-1,j]);71 最大子矩阵问题-----最大字段和问题f:=max(f[i-1]+b,b); f[1]:=b[1]72 最大子矩阵问题-----最大子立方体问题枚举一组边i的起始,压缩进矩阵B[I,j]+=a[x,I,j]枚举另外一组边的其实,做最大子矩阵73 括号序列-----线型动态规划f[I,j]:=min(f[I,j],f[i+1,j-1](ss[j]=”()”or(”[]”)),f[I+1,j+1]+1 (s[j]=”(”or”[” ] , f[I,j-1]+1(s[j]=”)”or”]” )74 棋盘切割-----线型动态规划f[k,x1,y1,x2,y2]=min{min{f[k-1,x1,y1,a,y2]+s[a+1,y1,x2,y2],f[k-1,a+1,y1,x2,y2]+s[x1,y1,a,y2]min{}}75 概率动态规划-----聪聪和可可(NOI2005)x:=p[p[i,j],j]f[I,j]:=(f[x,b[j,k]]+f[x,j])/(l[j]+1)+1f[I,i]=0f[x,j]=176 概率动态规划-----血缘关系F[A, B]=(f[A0, B]+P[A1, B])/2f[I,i]=1f[I,j]=0(I,j无相同基因)77 线性动态规划-----决斗F[I,j]=(f[I,j] and f[k,j]) and (e[I,k] or e[j,k]),i<k<j78 线性动态规划-----舞蹈家F[x,y,k]=min(f[a[k],y,k+1]+w[x,a[k]],f[x,a[k],k+1]+w[y,a[k]]) 79 线性动态规划-----积木游戏F[I,a,b,k]=max(f[I,a+1,b,k],f[i+1,a+1,a+1,k’],f[I,a+1,a+1,k’]) 80 树形动态规划(双次记录)----NOI2003 逃学的小孩朴素的话枚举节点i和离其最远的两个节点j,k O(n^2)每个节点记录最大的两个值,并记录这最大值分别是从哪个相邻节点传过来的。
动态规划算法题(5题)
动态规划算法题(5题)1、题⽬描述(⽹易)有 n 个学⽣站成⼀排,每个学⽣有⼀个能⼒值,⽜⽜想从这 n 个学⽣中按照顺序选取 k 名学⽣,要求相邻两个学⽣的位置编号的差不超过d,使得这 k 个学⽣的能⼒值的乘积最⼤,你能返回最⼤的乘积吗?输⼊描述:每个输⼊包含 1 个测试⽤例。
每个测试数据的第⼀⾏包含⼀个整数 n (1 <= n <= 50),表⽰学⽣的个数,接下来的⼀⾏,包含 n 个整数,按顺序表⽰每个学⽣的能⼒值 ai(-50 <= ai <= 50)。
接下来的⼀⾏包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。
输出描述:输出⼀⾏表⽰最⼤的乘积。
试题分析:本题要使⽤动态规划来解,动态规划的特点:1.求解的是最优化问题;2.可以分解为最优⼦结构本题可以先求解在第i个学⽣的位置下,j(j<K)个学⽣的能⼒值的最⼤值,得到所有学⽣位置下j个学⽣的能⼒值的最⼤值;在j个学⽣的情况下,得到j+1个学⽣的最⼤值,样例输出: 10 8 7 2 -7 9 5 4 10 -7 1 3 3输出: 630如上,第⼀步先计算k=2的情况:7:在d=3的情况下,最⼤最⼩值都为562:在d=3的情况下,最⼤值为16,最⼩值为14-7:在d=3的情况下,最⼤值为-14,最⼩值为-56......得到第⼀趟的结果k=3的情况下(这⾥以第⼀趟的结果为基础,只有这样就不需要考虑第⼀趟中d=3的限制):2:在d=3的情况下,最⼤最⼩值都为112(56*2)-7:在d=3的情况下,最⼤值为-98(14*-7)最⼩值为-392(56*-7)9:在d=3的情况下,最⼤值为504(56*9)最⼩值为-504(-56*9)......得到第⼆趟的结果返回最⼤值就是最后的结果#-*- coding:utf-8 -*-n=input()array=[int(i) for i in raw_input().split()]k,d=[int(i) for i in raw_input().split()]# n=36array_max=array_min=array#轮询k-1趟即可for i in range(0,k-1):_max=[-float('inf')]*n#将最⼤值的数组赋值⽆穷⼩_min=[float('inf')]*n#将最⼩值的数组赋值⽆穷⼤for j in range(i+1,n):if j<=d+i:#下⾯对应的min、max都是考虑到array[j]为负值的情况下temp_max = max(max(ii*array[j] for ii in array_max[i:j]),max(ii*array[j] for ii in array_min[i:j]))temp_min = min(min(ii*array[j] for ii in array_max[i:j]),min(ii*array[j] for ii in array_min[i:j]))else:temp_max = max(max(ii*array[j] for ii in array_max[j-d:j]),max(ii*array[j] for ii in array_min[j-d:j]))temp_min = min(min(ii*array[j] for ii in array_max[j-d:j]),min(ii*array[j] for ii in array_min[j-d:j]))_max[j]=temp_max_min[j]=temp_minarray_max=_maxarray_min=_minprint array_maxprint array_minprint max(array_max)2、题⽬描述(腾讯):腾讯⼤厦有39层,你⼿⾥有两颗⼀抹⼀眼的玻璃珠。
动态规划经典问题
动态规划经典问题动态规划(Dynamic Programming)是一种常用的求解最优化问题的方法,它通过将问题分解成若干子问题,并保存子问题的解,从而避免重复计算,提高计算效率。
在动态规划中,经典问题有不少,其中包括背包问题、最长公共子序列问题、最长递增子序列问题等。
本文将介绍其中的两个经典问题:背包问题和最长递增子序列问题。
一、背包问题背包问题是动态规划中的经典问题之一,它描述了一个给定容量的背包和一系列物品,每一个物品有自己的分量和价值,在限定的容量下,如何选择物品使得背包中的总价值最大化。
假设有一个背包,容量为W,有n个物品,每一个物品的分量分别为w1,w2, ..., wn,对应的价值分别为v1, v2, ..., vn。
要求在限定的背包容量下,选择一些物品放入背包,使得背包中物品的总价值最大。
解决背包问题的一种常用方法是使用动态规划。
我们可以定义一个二维数组dp,其中dp[i][j]表示在前i个物品中,背包容量为j时的最大价值。
根据动态规划的思想,我们可以得到如下的状态转移方程:dp[i][j] = max(dp[i-1][j], dp[i-1][j-wi] + vi)其中,dp[i-1][j]表示不选择第i个物品时的最大价值,dp[i-1][j-wi] + vi表示选择第i个物品时的最大价值。
具体求解背包问题的步骤如下:1. 初始化dp数组,将dp[0][j]和dp[i][0]均设为0,表示背包容量为0时和没有物品可选时的最大价值均为0。
2. 逐个计算dp[i][j]的值,根据状态转移方程更新dp数组。
3. 最终得到dp[n][W]的值,即为所求的最大价值。
例如,假设背包容量为10,有4个物品,它们的分量和价值分别如下:物品1:分量2,价值6物品2:分量2,价值3物品3:分量3,价值5物品4:分量4,价值8根据上述步骤,可以得到如下的dp数组:0 1 2 3 4 5 6 7 8 9 100 0 0 0 0 0 0 0 0 0 0 01 0 0 6 6 6 6 6 6 6 6 62 0 0 6 6 9 9 9 9 9 9 93 0 0 6 6 9 9 11 11 14 14 144 0 0 6 6 9 9 11 11 14 14 17可以看到,dp[4][10]的值为17,表示在背包容量为10时,选择物品1、物品3和物品4可以得到的最大价值为17。
动态规划应用动态规划解决问题的思路与技巧
动态规划应用动态规划解决问题的思路与技巧动态规划应用 - 动态规划解决问题的思路与技巧动态规划(Dynamic Programming)是一种常见的算法思想,用于解决一些具有重叠子问题和最优子结构性质的问题。
通过将大问题划分为小问题,并将小问题的解存储起来以避免重复计算,可以在一定程度上优化问题的求解过程。
本文将介绍动态规划的应用,并提供一些思路与技巧。
一、动态规划的基本思路动态规划问题通常可以由以下步骤解决:1. 定义状态:将问题划分成若干子问题,并确定每个子问题需要记录的状态。
2. 定义状态转移方程:通过分析子问题之间的关系,建立状态转移方程,以表达子问题的最优解与更小规模子问题的关系。
3. 初始化边界条件:确定最小规模子问题的解,并初始化状态转移方程中需要用到的边界条件。
4. 递推求解:按照状态转移方程的定义,从较小规模的子问题开始逐步推导出较大规模的问题的解。
5. 求解目标问题:根据最终推导出的状态,得到原始问题的最优解。
二、动态规划的技巧与优化1. 滚动数组:为了降低空间复杂度,可以使用滚动数组来存储状态。
滚动数组只记录当前状态与之前一部分状态相关的信息,避免了存储所有状态的需求。
2. 状态压缩:对于某些问题,可以将状态压缩成一个整数,从而大幅减小状态的数量。
例如,当问题中涉及到某些特定的组合或排列时,可以使用二进制位来表示状态。
3. 前缀和与差分数组:对于某些问题,可以通过计算前缀和或差分数组,将问题转化为求解累加或差对应数组中的某个区间的值的问题,从而简化计算过程。
4. 贪心思想:有些动态规划问题可以结合贪心思想,在每个阶段选择局部最优解,然后得到全局最优解。
5. 双重循环与多重循环:在实际解决问题时,可以使用双重循环或多重循环来遍历状态空间,求解问题的最优解。
三、动态规划的实际应用动态规划广泛应用于各个领域,包括但不限于以下几个方面:1. 最短路径问题:例如,求解两点之间的最短路径、最小生成树等。
力扣优秀题解
力扣优秀题解——动态规划动态规划(Dynamic programming,简称DP)是一种常见的求解优化问题的方法。
它与分治算法类似,都是通过将大问题分解成若干个小问题来求解的。
不同的是,DP解决的问题通常是有重叠子问题和最优子结构特征的,即在求解过程中会反复计算相同的子问题,并且每个子问题都具有最优解,可以通过这些最优解推导出全局最优解。
力扣中的很多题目都可以使用动态规划来解决,比如最长公共子序列、股票买卖、打家劫舍等等。
下面针对这些题目进行详细解析。
一、最长公共子序列题目描述:给定两个字符串text1 和text2,返回它们的最长公共子序列。
如果不存在公共子序列,返回0。
示例:输入:text1 = "abcde", text2 = "ace" 输出:3 解释:最长公共子序列是 "ace",它的长度为 3。
解题思路:最长公共子序列问题是比较经典的DP问题。
设字符串text1和text2的长度分别为m 和n,令dp[i][j]表示text1[0:i]和text2[0:j]的最长公共子序列长度,为方便起见,text1和text2的下标从1开始。
当text1[i-1] == text2[j-1]时,dp[i][j] = dp[i-1][j-1] + 1,即text1[0:i-1]和text2[0:j-1]的最长公共子序列长度加上1。
当text1[i-1] != text2[j-1]时,dp[i][j] = max(dp[i-1][j], dp[i][j-1]),即考虑text1[0:i-1]和text2[0:j]的最长公共子序列长度与text1[0:i]和text2[0:j-1]的最长公共子序列长度,两者取最大值。
最终的答案即为dp[m][n]。
代码实现:class Solution: def longestCommonSubsequence(self, text1: str, text2: str) -> int: m, n = len(text1), len(text2) dp = [[0] * (n + 1) for _ in range(m + 1)] for i in range(1, m + 1): for j in range(1, n + 1): if text1[i - 1] == text2[j - 1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) return dp[m][n]二、股票买卖题目描述:给定一个数组prices,其中prices[i]是一支给定股票第i天的价格。
动态规划经典问题大合集
动态规划经典教程引言:本人在做过一些题目后对DP有些感想,就写了这个总结:第一节动态规划基本概念一,动态规划三要素:阶段,状态,决策。
他们的概念到处都是,我就不多说了,我只说说我对他们的理解:如果把动态规划的求解过程看成一个工厂的生产线,阶段就是生产某个商品的不同的环节,状态就是工件当前的形态,决策就是对工件的操作。
显然不同阶段是对产品的一个前面各个状态的小结,有一个个的小结构成了最终的整个生产线。
每个状态间又有关联(下一个状态是由上一个状态做了某个决策后产生的)。
下面举个例子:要生产一批雪糕,在这个过程中要分好多环节:购买牛奶,对牛奶提纯处理,放入工厂加工,加工后的商品要包装,包装后就去销售……,这样每个环节就可以看做是一个阶段;产品在不同的时候有不同的状态,刚开始时只是白白的牛奶,进入生产后做成了各种造型,从冷冻库拿出来后就变成雪糕(由液态变成固态)。
每个形态就是一个状态,那从液态变成固态经过了冰冻这一操作,这个操作就是一个决策。
一个状态经过一个决策变成了另外一个状态,这个过程就是状态转移,用来描述状态转移的方程就是状态转移方程。
经过这个例子相信大家对动态规划有所了解了吧。
下面再说说我对动态规划的另外一个理解:用图论知识理解动态规划:把动态规划中的状态抽象成一个点,在有直接关联的状态间连一条有向边,状态转移的代价就是边上的权。
这样就形成了一个有向无环图AOE网(为什么无环呢?往下看)。
对这个图进行拓扑排序,删除一个边后同时出现入度为0的状态在同一阶段。
这样对图求最优路径就是动态规划问题的求解。
二,动态规划的适用范围动态规划用于解决多阶段决策最优化问题,但是不是所有的最优化问题都可以用动态规划解答呢?一般在题目中出现求最优解的问题就要考虑动态规划了,但是否可以用还要满足两个条件:最优子结构(最优化原理)无后效性最优化原理在下面的最短路径问题中有详细的解答;什么是无后效性呢?就是说在状态i求解时用到状态j而状态j求解又用到状态k…..状态N。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态规划:【1】.矩阵乘法链,最小乘法次数。
一、问题描述给定一个矩阵序列<A1,A2,…,An>,计算乘积A1A2…An。
要求找出一个加全部括号的方式,使得标量乘法的次数最小。
对于任意两个矩阵AiAi+1相乘,其乘法次数为pi-1pi pi+1,不同的加全部括号,所需要的乘法次数可能相差很大。
假设现在有三个矩阵A1A2A3相乘,维数分别为:10×100,100×5,5×50。
1、如果我们采用如下方式加全部括号:((A1A2)A3)则首先计算(A1A2),乘法次数为p0p1 p2,得到新矩阵的维数为p0×p2计算((A1A2)A3),乘法次数为p0p2 p3,总的计算次数为p0p1 p2+ p0p2 p3=10×100×5+10×5×50=75002、如果我们采用如下方式加全部括号:(A1(A2 A3))则首先计算(A2 A3),乘法次数为p1 p2 p3,得到新矩阵的维数为p1×p3计算(A1(A2 A3)),乘法次数为p0p1 p3,总的计算次数为p1 p2 p3+ p0p1 p3=100×5×50+10×100×50=75000第二种方式需要的次数是第二次的10倍!二、问题分析:由前面可知,一个序列如果只有一个矩阵,则只有一种方式加全部括号,如果有两个或两个以上的矩阵,则必然可以看做两个子序列的乘积,且这两个子序列也是加全部括号。
我们用cost(i,j)表示序列Ai…Aj在最优加全部括号时的标量乘积次数,则其中p(i-1)p(k) p(j)为子序列Ai…Ak与Ak+1…Aj相乘时的标量相乘次数。
顺序连城可以把最后一个单个的看成单独加括号。
三、问题求解每一对满足1≤i≤j≤n的i和j都对应原问题的一个子问题,子问题个数为动态规划(二):矩阵链乘法,其中第一项表示i<j时的子问题个数,后一项表示i=j 时的子问题个数。
如果采用递归方法求解,则每个子问题都会被求解多次,可以保留中间结果。
另外我们也采用自底向上的动态规划方式求解。
首先定义一个二维矩阵value,value[i][j]存放子序列Ai…Aj在最优加全部括号时的标量乘积次数,我们只使用j>=i的部分,且value[i][i]=0。
动态规划的实现步骤如下:步骤一:令step=0;步骤二:对于所有i=0,…,n,计算并保存value[i][i+step];步骤三:若step=n-1,则结束,否则step=step+1,返回步骤二。
矩阵维数A130×35A235×15A315×5A45×10A510×20A620×25//实现思想:1.令step不同,即(j-i)不同;2.从i到j选择不同的分割点k。
i =< k < j;求出极大值。
记录分割的位置。
三重循环,从底层开始;首先分析:step=1,得到组合(1,2)、(2,3)、(3,4)、(4,5)、(5,6);step=2,得到组合(1,3)、(2,4)、(3,5)、(4,6);而其中,step=2,要用到不同的k了。
(1,2)3或者1(2,3);同理step=3,得到组合(1,4)、(2,5)、(3,6);要用到不同的k了。
1(2,3,4)或者(1,2)(3,4)或者(1,2,3)4;这些都是step 为小的时候得到的。
最终得到的step=5,得到组合(1,6)。
才是我们需要的。
【2】.装配线调度问题。
现有两条装配线,Sij表示第i条上完成第j道工序的装配站。
汽车完成组装需要依次完成1~n工序。
请找出完成装配并离开装配线的最快路线。
符号说明:ei:汽车进入装配线i的时间,i=1,2xi:汽车离开装配线i的时间aij:在装配站Sij完成装配需要的时间tij:在装配站Sij完成后离开第i条装配线,进入另一条装配线需要的转移时间注意,如果完成工序后,下一个工序还在同一条装配线上,则不需要转移时间。
问题求解:用Fij表示在第i条装配线上完成第j道工序的最快时间,用F表示完成汽车装配并离开装配线的时间,如果知道F1n和F2n,则有:要求出F1n和F2n,需要知道F1n-1和F2n-1,则有故得到递推公式:2、动态规划如果我们不是从上到下求解,而是从下到上求解,求解结果在某个地方保存起来,则可以大大改善求解速度。
这里的动态min只有两个部分,只有一个存在递归的形式,而上面哪一个却又两个递归的部分。
// 同理递增也是一样的,动态规划,甚至更简单写,由于只是自身的记录。
而公共的则是两个。
原理都是动态规划的。
【3】.最长公共子序列问题和编辑距离问题。
longest common subsequence。
子序列是不要求连续相等的字符序列。
这个问题也是算法导论上提过的问题。
注意这个问题是Subsequence不是Substring。
substring的话就是子串,子串的要求的连续相等的字符序列,而subsequence不要求连续。
比如说ABCD和ABD。
他们的longest common subsequence就是ABD。
而Longest common substring就是AB。
这个问题和Edit Distance是同样的一类问题。
解决这类的问题都是从一个优化的子结构开始得到递推式,从而给出一个一般的全局优化结构的过程。
在这里,我们假定两个字符串分别是S1和S2。
他们的长度是m和n。
我们用M[i,j]来表示一个长度为i的S1和长度为j的S2的最优方案。
我们要找的就是当M[m,n]是的方案。
问题的关键就是要找到M[i,j]和之前的那些诸如M[1..i, 1..j]之间的关系。
// m*n;我们把问题分成两种情况来讨论:1. 如果S1[i] == S2[j]。
就是i,j对应位置上的字符相等。
那么可以得出M[i,j] = M[i-1,j-1]+1;为什么呢?可以想象的。
如果M[i-1,j-1]也是一个最后方案,在这个最优方案上我们同时增加一个字符。
而这两个字符又相等。
那么我们只需要在这个M[i-1,j-1]的最优方案上++就可以了。
2. 如果S1[i] != S2[j]。
那么就拿M[i-1,j]和M[i,j-1]来比较。
M[i,j]的值就是M[i-1,j]和M[i,j-1]中大的值。
这好比原来的字符串是S1[1...i-1]是ABC,S2[1...j-1]是ABE。
那S1[1..i]是ABCE,S2[1..j]是ABEC。
可以看出来这个时候M[i,j]不是由M[i-1,j-1]决定的,而是由ABCE和ABE或者ABC和ABEC来决定的,也就是M[i-1,j]和M[i,j-1]。
所以我们可以把这个问题的递归式写成:【4】.编辑距离。
问题抽象归类:(编辑距离问题)设A和B是2个字符串。
要用最少的字符操作将字符串A转换为字符串B。
这里所说的字符操作包括:(1)删除一个字符;(2)插入一个字符;(3)将一个字符改为另一个字符。
将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。
试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。
这个问题是动态规划中非常基础的一个问题,这个问题其实和另一个前面提到的问题很类似。
就是Edit Distance的问题。
编辑距离问题:Edit Distance问题又被成为Levenshtein distance问题。
这里的问题描述的就是两个字符串经过若干次修改(添加字符,删除字符,替换字符)变为两个完全相等字符串。
这里的distance就是指最少的修改次数。
其实这个也就是《编程之美》中的那个字符串相似度的问题。
相似的,我们还是定义一个M[i,j]的二维模型。
这时候一样还是分析M[i,j]的递归式。
这里的结果还是比较相近的。
如果S1[i] == S2[j]。
那么M[i,j]就等于M[i-1,j-1],就是说在S1[i]==S2[j]的情况下M[i,j]不会发生变化,显然不需要做什么改动。
edit(i, j) = edit(i-1, j-1);如果S1[i] != S2[j]的时候,那么就是M[i-1,j-1],M[i-1,j]和M[i,j-1]来做比较,我们取最小的那个值+1就可以了。
这里的M[i-1,j-1],M[i-1,j]和M[i,j-1]对应了添加、删除、替换这些操作。
M[i-1,j-1]可以替换最后一个S1[i]和S[j]来完成,而M[i-1,j]可以通过添加S1[i]来完成匹配。
edit(i, j) = min{edit(i-1, j)+1, edit(i, j-1)+1, edit(i-1, j-1)+1}对应添加,删除和替换这三个操作。
【5】.最长递增子序列(longest increase subsequence)既然已经说到了最长公共子序列,就把这个递增子序列也说了。
同样的,这里subsequence表明了这样的子序列不要求是连续的。
比如说有子序列{1, 9, 3, 8, 11,4, 5, 6, 4, 19, 7, 1, 7 }这样一个字符串的的最长递增子序列就是{1,3,4,5,6,7}或者{1,3,4,5,6,19}。
其实这个问题和前面的最长公共子序列问题还是有一定的关联的。
假设我们的初始的序列S1。
那我们从小到大先排序一下。
得到了S1'。
这样我们再求S1和S1'的最长公共子序列就可以知道答案了:)是不是有点巧妙啊。
这个过程还是比较直观的。
但是这个不是这次要说的重点,这个问题有比较传统的做法的:我们定义L(j)是一个优化的子结构,也就是最长递增子序列.那么L(j)和L(1..j-1)的关系可以描述成:L(j) = max{1; L(i)+1, (Ai<Aj)}; 所有的i<j;也就是说L(j)等于之前所有的L(i)中最大的的L(i)加一.这样的L(i)需要满足的条件就是Ai<Aj.这个推断还是比较容易理解的.就是选择j之前所有的满足小于当前数组的最大值.这里说满足无后效性。
即是前一阶段按照一定的次序排列好之后,对于某个给定阶段的状态来说,它以前各阶段的状态无法直接影响它未来的决策,只能间接地通过当前状态来影响。
比如一次为例如果有1,-1,2,-3,4,-5,6,-7.当i=3时。
前面有两个递增序列为(1,2)和(-1,2),长度都为2,这里2前面是1还是-1对求后面的递增序列没有直接的影响。
无后效。
上式子的意思即是,如果对所有的Aj>Ai,那么第i个元素可以直接接在L(i)子序列之后构成一个更长的子序列。