适用动态规划的特点

  1. 所解决的问题是最优化问题。
  2. 所解决的问题具有“最优子结构”。可以建立一个递推关系,使得n阶段的问题,可以通过几个k<n阶段的低阶子问题的最优解来求解。
  3. 具有“重叠子结构”的特点。即,求解低阶子问题时存在重复计算。

词典法

大家都知道,递归算法一般都存在大量的重复计算,这会造成不必要的时间浪费。词典法,它可以使递归函数避免重复计算。词典法的具体做法是,设计一个数据结构D(多为数组)来保存以前的计算结果。在计算过程中,如果发现要用到的计算结果是之前已经算过了的结果时,就可以直接从数据结构D中获取,避免重复计算,用空间换取时间。

动态规划同样使用了类似“词典法”的措施,也设计了一个数据结构来保存计算结果,但不再使用递归函数来求解,而是通过循环迭代的方式来填写数据结构。

动态规划常见问题

最长公共子序列

如果序列 { s1, s2, ……, sk } 是序列 { a1, a2, ……, an } 的子序列,又是序列 { b1, b2, ……, bm } 的子序列,则称序列 s 为序列 a 和 序列 b 的公共子序列。在 a 和 b 的所有公共子序列中,长度最长者称为最长公共子序列。 求a,b的最长公共子序列。

解析: 一个长度为n的序列,有2的n次方个子序列;如果用穷举的方法来比的话,那么时间复杂度将会非常高。很明显这是一个最优化的问题,我们不妨看看这期间存不存在递推关系,尝试寻找一下“最优子结构”。

假设S={s1,s2,...sk}是序列A={a1,a2,...an}和B={b1,b2...bm}的最长子序列,那么有以下发现:

  1. 如果an=bm,则{s1,s2...s(k-1)}是{a1,a2,...a(n-1)}和{b1,b2,...b(m-1)}的最长子序列;
  2. 如果an!=bm,则S要么是A(n-1)和B的最长公共子序列,要么是A和B(m-1)的最长公共子序列。

根据上面的分析,此问题存在着递推关系(“最优子结构”)。为方便,先计算最长公共子序列的长度,然后再寻找最长公共子序列。考虑用一个 二维数组D[i][j] 来记录A(i),B(j)的最长公共子序列的长度。由上面的分析,很容易得到以下:

  • D[i][j]=0,如果i或j为0;
  • D[i][j]=D[i-1][j-1]+1,如果ai=bj;
  • D[i][j]=max(D[i-1][j],D[i][j-1]),如果ai!=bj

由上面的递推公式可知,D[i][j]的计算有可能要用到i,j位置上一行的数以及i,j位置所在行左边的数,所以填写D[i][j]是应该是由上往下、由左往右填写,最后的D[n][m]就是A和B的最长公共子序列的长度。

C++实现如下:

#define MAX 100
#define max(a,b) a>b? a:b int D[MAX][MAX];//记录最长公共子序列的长度 int S[MAX];//记录其中一个公共最长子序列 void countLen(int A[], int n, int B[], int m) {//根据公式填写D[i][j]
int i, j;
for (i = 1; i <= n; i++)//i=0,j=0不用
for (j = 1; j <= m; j++)
if (A[i] == B[j])
D[i][j] = D[i - 1][j - 1] + 1;
else
D[i][j] = max(D[i - 1][j], D[i][j - 1]);
} int searchS(int A[], int n, int B[], int m) {//如果D[i]j]==D[i-1][j-1]+1,则A[i]可写进S;
int i, j, k;
i = n;
j = m;
k = D[n][m];
while (i != 0 && j != 0) {
if (D[i][j] == D[i - 1][j - 1])
i--;
else if (D[i][j] == D[i][j - 1])//也可沿着D[i][j]==d[i-1][j]回溯
j--;
else
{
S[k--] = A[i];
i--;
j--;
}
}
//返回最长长度
return D[m][n];
}

其他问题

  • 最大字段和问题
  • 矩阵连乘问题
  • 数据压缩问题
  • 0-1背包问题
  • 最优二叉树搜索问题

【原创声明。转载请标注原文地址:https://blog.csdn.net/yunyunyx/article/details/84140780】

最新文章

  1. 系统yum源更新及某些软件官方源安装
  2. CSS background 属性 总结
  3. cocos2d-x注意事项(十)Lua发展飞机战争-4-创建主角
  4. android studio IDE 下,设置ACTIVITY全屏
  5. 大型互联网公司Java开发岗位面试题归类!
  6. solaris启动过程详解
  7. [论文阅读] Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks(MTCNN)
  8. Java线程监控及中断
  9. c# throw和throw ex
  10. Windows Server 2012 R2 英文版安装中文语言包教程
  11. c++ — 运算符重载与strcmp自实现
  12. 谈谈逆向android里面的so
  13. jQuery之必会增删改查Dom操作
  14. select下拉菜单实现通过数据库查询来设置默认值
  15. 信号量 Linux函数 semget();semctl();semop();(转)
  16. MapReduce – 基本思路之推荐引擎
  17. multi thread for Java
  18. Linux下rz,sz与ssh的配合使用,实现文件传输
  19. C# 开发者代码审查清单
  20. Oracle 数据库数据结构(包括存储过程,函数,表,触发器等)版本控制器

热门文章

  1. JS 拖动原理
  2. final可以修饰类、属性、方法
  3. [ACM] FZU 2086 餐厅点餐 (枚举)
  4. 转载:pyqt的signal和solit
  5. [NOIP 2014复习]第二章:搜索
  6. Oracle的归档日志
  7. UILabel 行间距设置
  8. Codeforces Round #190 (Div. 2).D
  9. c#基础 第一讲
  10. 【BZOJ1070】[SCOI2007]修车 费用流