动态规划
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法一:递归的思想 设两个字符串分别是 char str1[MAXL]; 长度是len1 char str2[MAXL]; 长度是len2 设f(str1,len1,str2,len2)为str1和str2的最大 公共子串的长度,则可以对两个字符 串的最后一个字符的情况进行枚举: 情况一:str1[len1-1] == str2[len1-1],则
动 态 规 划
例10 POJ 1458最大公共子串 给出两个字符串,求出这样的一个 最长的公共子序列的长度:子序列 中的每个字符都能在两个原串中找 到,而且每个字符的先后顺序和原 串中的先后顺序一致。 Sample Input abcfbc abfcab programming contest abcd mnp Sample Output 4 2 0
return 1+MaxStr(str1,len1-1,str2,len2-1);
else if(MaxStr(str1,len1-1, str2,len2)>MaxStr(str1,len1,str2,len2-1)) return MaxStr(str1,len1-1,str2,len2); else return MaxStr(str1,len1,str2,len2-1);
程序如下:
#include "stdio.h" #include "memory.h" #include "string.h" char str1[100]; char str2[100]; int MaxStr(char *s,int len1,char *t,int len2) { if(len1==0||len2==0) return 0; else if(str1[len1-1] == str2[len2-1])
7
3 8 8 1 0 2 7 4 4 4 5 2 6 5
30 23 21 20 13 10 7 12 10 10 4 5 2 6
5 7 3 8 2 4
1 1 1 1 1
8 1 7 5
0 4 4 2 6
5
5ຫໍສະໝຸດ 20 1 21 2 1 22 3 3 1 23 4 6 4 1 24
动态规划:将一个问题分解为 子问题递归求解,将中间结果 保存以避免重复计算的方法。 求最优解 一切子问题也是最优的
递归
递推
i=n
aMaxSum[i][j]= elem[i][j]
max(aMaxSum(i+1,j),aMaxSum(i+1,j))
i<n
算法二:动态规划从下往上逐层计算
动 态 规 划
例11 POJ 2755 神奇口袋 前面介绍了用递归的方法解此题,核 心思想是逐一枚举每个数的使用情 况,用或不用,这里可以用动态规 划的方法实现这一想法.即有n个 数,则用1到2n所表示的二进制数来 枚举所有这些数的组合情况,例如: n=3,则5->101表示用第1 和第3个数,不用第2个数,检验 有多少种组合的和是40,就得到 了问题的解.
解决重复计算的方法: 将中间计算结果保存起来,从 而不必每次都递归计算。 每个结点只计算一次 总计算次数=1+2+3+…+n
#include "stdio.h" #include "memory.h" int n; int elem[101][101]; int aMaxSum[101][101]; int MaxSum(int row,int col) { if(row==n) return elem[row][col]; if(aMaxSum[row+1][col]==-1) aMaxSum[row+1][col]=MaxSum(row+1,col); if(aMaxSum[row+1][col+1]==-1) // //
f(str1,len1,str2,len2) = 1+ f(str1,len1-1,str2,len2-1)
情况二:str1[len1-1] != str2[len1-1]
f(str1,len1,str2,len2) = max(f(str1,len1-1,str2,len2), f(str1,len1,str2,len2-1))
int i,j; while(1) { gets(str1);if(str1[0]=='\0') break; gets(str2);
void main() { char ch; while((ch = getchar()) != EOF) putchar(ch);
} CTRL+Z
树 形 递 归
例8:POJ 2753 Fibonacci数列 1,1,…,f(n-1)+f(n-2),… int f(int n){ if(n==0 || n==1) return n; return f(n-1)+f(n-2); }
例8:POJ
2753 Fibonacci数列
计算过程中存在冗余计算,为了出去冗余计算 可以从已知条件开始计算,并记录计算过程中 的中间结果。 f(5)
int n; int elem[101][101]; int MaxSum(int row,int col) { if(row==n) return elem[row][col]; // int nSum1=MaxSum[row+1][col]; // int nsum2=MaxSum[row+1][col+1]; if(MaxSum(row+1,col)>=MaxSum(row+1,col+1)) return MaxSum(row+1,col)+elem[row][col]; else return MaxSum(row+1,col+1)+elem[row][col]; } int main(int argc, char* argv[]) { scanf("%d",&n); int i,j; for(i=1;i<=n;i++) for(j=1;j<=i;j++)
递归和动态规划
递归: (1)将原问题分解为更小规模的同类问题 (2)结束条件
内 容 提 要
#include "stdio.h" int factorial(int n) { if(n<=0)return(-1); if(n==1) return(1); else return n*factorial(n-1); }
算法一:递归的想法 设f(i,j) 为三角形上从点(i,j)出发向下 走的最长路经,则 f(i,j) = max(f(i+1,j), f(i+1,j+1))+d[i][j] 要输出的就是f(1,1,)即从最上面一 点出发的最长路经。
代码如下:
树 形 递 归
f(1)
1
f(4) f(3) f(2) f(2) f(2)
f(3) f(1) 1
f(1) f(1) f(0) f(1) f(0) 0 0 1 0
f(1) f(0) 1 1 0
冗余计算
动 态 规 划
例8:POJ 2753 Fibonacci数列 int f[n+1]; f[1]=f[2]=1; int I; for(i=3;i<=n;i++) f[i] = f[i-1]+f[i-2]; cout << f[n] <<endl;
动态规划的实质就是
动 态 规 划 的 实 质
就是将用递归解决时会重复计算的值, 算好一次后就存起来,以后不必重 新计算,用空间换时间。动态规划 通常用求最优解,能用动态规划解 决的求最优解问题,必须满足最优 解的每个局部也都是最优的。
例9 POJ 1163 数字三角形
7
动 态 规 划
3 8 2 4 5 7 2 1
aMaxSum[row+1][col+1]=MaxSum(row+1,col); int nSum1=MaxSum[row+1][col]; int nsum2=MaxSum[row+1][col+1]; if(MaxSum(row+1,col)>=MaxSum(row+1,col+
1)) return MaxSum(row+1,col)+elem[row][col]; else
Sets buffers to a specified character. void *memset( void *dest, int c, size_t count ); dest Pointer to destination c Character to set count Number of characters
#include "stdio.h" #include "memory.h" #include "string.h" #define MAX 100 char str1[MAX]; char str2[MAX]; int com[MAX][MAX]; int main(int argc, char* argv[]) {
int main(int argc, char* argv[]) { printf("%d\n",factorial(5)); getchar(); return 0; }
f(5)
f(4) 线性的 f(3) f(2) f(x)->g(f(x-x’)) 每个f(x-x’)只 计算一次。
f(1)
解题步骤: (1)问题分解为子问题 越来越简单 最终直接有解 (2)状态:子问题对应的变量 的值及结果 (3)状态迁移 从已知状态推导未知状态
aMaxSum[i][j]=
elem[i][j]
i=n max(aMaxSum(i+1,j),aMaxSum(i+1,j)) i<n
8 0 4 6 4 5
在上面的数字三角形中寻找一条从顶部到底 边的路径,使得路径上所经过的数字之和 最大。路径上的每一步都只能往左下或右 下走。只需要求出这个最大和即可,不必 给出具体路径。 三角形的行数大于1小于等于100 数字为0 - 99
输入格式:
5 //三角形行数。下面是三角形 7 38 810 2744 45265 要求输出最大和
递归过程如下: abcfbc abfcab abcfb abfcab abcf abfca abc abfca ab abfca a abfca '' abfca
算法二:动态规划 从str1和str2的第一个字符开始考虑; int comLen[MAX][MAX]; 用一个二维数组记录str1的前i个字符与str2中的前j个字符 的最大公共子串长度.(状态) 设立初值: comLen [0][0~MAX]=0; comLen [0~MAX][0]=0; 表示两个字符串中有一个没有参与比较时,最大公共 子串长度为0. 递推: if(str[i]==str[j]) comLen [i][j] =1+ comLen [i-1][j-1]; else comLen[i][j] = max(comLen[i-1][j],comLen[i][j-1]);
#include "memory.h" int n; int elem[101][101]; int aMaxSum[101][101]; int main(int argc, char* argv[]) { scanf("%d",&n); memset(aMaxSum,-1,sizeof(aMaxSum)); int row,col; for(row=1;row<=n;row++) for(col=1;col<=row;col++) scanf("%d",&elem[row][col]); for(row=n;row>=1;row--) for(col=1;col<=row;col++)