算法总结之动态规划(DP)

适用动态规划的特点

  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】

posted @ 2018-11-17 15:01  Sure_Cheun  阅读(502)  评论(0编辑  收藏  举报