为了账号安全,请及时绑定邮箱和手机立即绑定

算法总结之动态规划(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:bint 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

【原创声明】转载请标明出处:

https://www.cnblogs.com/surecheun/  


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消