一 动态规划的基本思想以及和贪婪算法、分治法的比较

动态规划的基本思想:将复杂问题进行分解,通过求解小规模子问题反推出原问题的结果。动态规划适合求解多阶段决策问题的最优解(可以简单理解为有状态转换的阶段性问题)。这些问题必须满足最优化原理和子问题的无后向性。

最优化原理:不管之前的决策是否最优,但是一定要保证从现在开始的决策是在之前决策基础上的最优决策。

无后向性原理:当各个子阶段的子问题确定以后,对于某个特定阶段的子问题来说,它之前的各个阶段的子问题的决策只影响当前阶段的决策,而对该阶段之后的决策不产生影响。即每个阶段的决策只受之前决策的影响,不影响之后各阶段的决策。

动态规划与贪婪算法以及分治法的比较:

三者都需要对原问题进行分解,分解为需要求解的子问题。分治法求解的子问题是独立的,每个问题的求解模式一样,分别求解再合并就是原问题的解。而贪婪算法只考虑当前状态,并依据贪婪法则取得局部最优解,直到扩展到原来的问题。动态规划的子问题需要满足最优化原理和无后向性原理。

解决动态规划问题的关键是找到状态转换方程。下面介绍一些常见的应用:

一 最长公共子序列

问题:对两个子序列S和T,求解S和T最大公共子序列的长度。

例如 S:ABCDEF;T:ACDF。则最大子序列为ACDF。

分析:假设a[i][j]表示S中下标[0,i]和T中下标[0,j]之间序列的最大公共子序列。分析可知:

代码如下:

int maxCommonSubsequence(const string& s1, const string& s2)
{vector<vector<int>> a(s1.size() + 1, vector<int>(s2.size() + 1, 0));for (int i = 1; i <= s1.size(); i++){for (int j = 1; j <=s2.size(); j++){if (s1[i - 1] == s2[j - 1]){a[i][j] = 1 + a[i - 1][j - 1];}else{a[i][j] = max(a[i-1][j],a[i][j-1]);}}}return a[s1.size()][s2.size()];
}

假如对上面的最长子序列加一个限制,改为最长连续公共子序列。又该如何求解呢?

代码如下:

int maxConsecutiveSubsequence(const string& s1, const string& s2)
{vector<vector<int>> a(s1.size() + 1, vector<int>(s2.size() + 1, 0));int res = 0;for (int i = 1; i <= s1.size(); i++){for (int j = 1; j <=s2.size(); j++){if (s1[i - 1] == s2[j - 1]){a[i][j] = 1 + a[i - 1][j - 1];res = max(res, a[i][j]);}else{a[i][j] = 0;}}}return res;
}

二 最长递增子序列

问题:给定一个数组,求最长递增子序列长度。比如a[10]={4,0,2,6,1,3,5,9,6,7,8},则最长递增子序列为:0,1,3,5,6,7,8。

分析:假设数组为V,记从[0,k]之间的最长递增子序列长度为result[k],则有:

result[k]=1+max{result[i]|0<=i<=k-1&&(V[i]<=V[k])}

代码如下:

int max_inc_seq(const vector<int> & s)
{int res = 0;vector<int> result(s.size(), 0);result[0] = 1;for (int i = 1; i < s.size(); i++){result[i] = 1;for (int j = 0; j < i; j++){if ((s[j]<=s[i]) && result[i]<(result[j] + 1)){result[i] = result[j] + 1;res = max(res, result[i]);}}}return res;
}

三 0-1背包问题

问题描述:有N件物品和一个承重为C的背包,每件物品的重量是Wi,价值为Pi,在不超过背包容量的前提下,求那几件物品可以使

背包中价值最大?

分析:假设p[i][w]表示前i个物品的最优背包解,背包容量是w。分析状态转换关系:

代码如下:

int pack(const vector<int> &w, const vector<int> &p, int W, vector<int> &every_element)
{vector<vector<int>> a(w.size() + 1, vector<int>(W + 1, 0));for (int i = 1; i <= w.size(); i++){for (int j = 1; j <= W; j++){if (w[i - 1]<= j){a[i][j] =(((a[i - 1][j])>(p[i - 1] + a[i - 1][j - w[i - 1]])) ? (a[i - 1][j]) : (p[i - 1] + a[i - 1][j - w[i - 1]]));}else{a[i][j] = a[i - 1][j];}}}for (int i =w.size(), j =p.size(); i >= 1 && j >= 1;){if (a[i][j] ==a[i - 1][j]){i--;}if (j >= w[i - 1] && a[i][j]==(p[i - 1] + a[i - 1][j - w[i - 1]])){every_element.push_back(p[i - 1]);j -= w[i - 1];i--;}}return a[w.size()][W];
}

个人感觉动态规划问题的关键在于找到一个状态转换方程,或者说是一个递推关系。没有一个固定的模式,必须自己分析出来。

同时利用数组存储中间的运算变量,可以提高效率。

四 最长回文子串

问题描述:给定一个字符串,求字符串的最长回文子串。

思路:之前遇到这个问题时,思路是,对该字符串和字符串本身逆序求其最长连续公共子序列,即转化为最长公共子序列问题。后来发现其实是错误的,比如对于子序列:1234354321,其最长回文子序列为343,长度为3,。若是按照这种思路,序列1234354321和1234534321的最长连续公共子序列为1234或者4321,其长度为4。说明这种想法是错误的。后来在leetcode上发现了一种新的思路,也是动态规划。思路为:设状态为f(i,j),表示区间[i,j]是否为回文串,则状态转移方程为:

代码如下:

int getLongestPalindrome(string A, int n) {// write code herevector<vector<bool>> v(n,vector<bool>(n,false));int res=1;for(int i=0;i<n;++i){v[i][i]=true;for(int j=0;j<i;++j){v[j][i]=(A[i]==A[j]&&(i-j<2||v[j+1][i-1]));if(v[j][i]){if(res<i-j+1)res=i-j+1;}}}return res;}

动态规划思想以及常见应用相关推荐

  1. 从背包问题优化详解动态规划思想

    动态规划: 所有的数据结构与算法的理解必须建立在题目的练习上,否则看多少理论都没有实际用处!!! 所以下面这些理论文字看不懂通通没关系,跟随下面的背包问题还会跟深入的理解. 一.基本概念:任何数学递推 ...

  2. python动态规划算法最大k乘积_C语言使用DP动态规划思想解最大K乘积与乘积最大问题...

    最大K乘积问题设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 编程任务: 对于给定的I 和k ...

  3. 应用动态规划思想解决实际问题

    从概念和原理出发去学习某个知识点,往往有种晦涩.无从下手的感觉,本文列举两个示例,从实际应用的角度来理解"动态规划"思想. 数字三角形问题 "数字三角形"是动态 ...

  4. 数据结构与算法——动态规划思想解题三角形问题

    动态规划的基本思想 动态规划解题的时候将问题分解为几个不同的阶段(把原始问题分解为不同的子问题),自底向上计算.每次决策都依赖于当前的状态.我们可以将不同阶段的不同状态存储在一个二维数组中. 从这个二 ...

  5. 动态三角形(动态规划思想入门)

    个人心得:动态规划是一种隶属于决策学的一个算法思想,他能够很好的解决多阶段决策问题,这种思想对于我们的生活还是科研都是必不可少的, 需要好生体会,学会动态方程的转移,做到具体问题具体分析. 那这简单题 ...

  6. 动态规划思想——最优二叉搜索树问题(附完整的代码)

    问题: 最优二叉搜索树问题的问题提出是,设S={x1, x2, ..., xn}是一个由n个关键字组成的线性有序集,(a0, b1, a1, ..., bn, an) 为集合S的存取概率分布,表示有序 ...

  7. POJ-1664 放苹果 动态规划思想解组合数学

    该题说明了状态开设的意义一样,但是从哪个方向去理解推倒状态的转移对解题非常关键.该题扣住是否所有的盘子中有空盘子,就得到了一个非常简单且优美的方程.如果从当前盘子的放置状态或者是当前苹果的放置状态来求 ...

  8. 动态规划思想-----求数组中出现最多数

    问:一个数组中,有一个数出现的次数大于数组长度的一半,求出这个数 #选择出出现次数最多的那个数字 #假定那个数的次数大于数组中的数目总和的一半以上 #思路: #那么我们可以认为这个数字的出现数字大于其 ...

  9. 动态规划从理论到实践-深入理解贪心/分治/回溯/动态规划的算法思想

    摘要:本文主要讲解常见的四种算法,分别为贪心算法:第一步选择最优的走法,算法不能做到全局最优:分治算法:一种处理问题的思想,使用递归来实现:回溯算法:我们枚举所有的解,找到满足期望的解,可以把求解过程 ...

最新文章

  1. SQL SERVER 2008权限配置
  2. linux 测试vim编译器_推荐几个好用的在线编译器
  3. 编程之美-2.14-求数组的子数组之和的最大值
  4. vue项目打包之后原本好的样式变得不好了的原因分析
  5. 蒙特卡洛法—非均匀随机数的产生
  6. mysql idle_MySQL常用指令
  7. 第一讲,Python的安装(干货)
  8. TripleDES类 3des加密算法实现
  9. iview Table列表中增加字体图标
  10. CF 1475 D. Cleaning the Phone 思维模型
  11. 逆向课程第二讲,寻找main入口点
  12. dede列表分页php,织梦用dede:sql实现列表页分页教程
  13. 基于linux桌面3d面打印机,基于DLP技术的桌面级3D打印机研发
  14. couchdb 视图操作_CouchDB 教程
  15. 截图工具Snagit试用免费激活方法
  16. 联想开机壁纸存放位置
  17. 阿里云吴磊创办yunQ云桥,完成银杏谷资本2000万元天使轮融资
  18. 嵌入式在生活中的应用
  19. 动态规划求解多段图问题
  20. HTML页面元素及属性

热门文章

  1. Mastering Atari, Go, Chess and Shogi by Planning with a Learned Model (MuZero)
  2. Bringing down service while still waiting for start foreground
  3. java有向图最短路径_单源最短路径之Java实现(使用Java内置优先队列)
  4. PHP 链接数据库1(连接数据库简单的登录注册)
  5. windows mysql服务消失,创建服务后mysql错误1607无法启动
  6. 哈希的应用(2)——布隆过滤器
  7. ognl是个什么东东呢?
  8. Nordic 52832 BLE Central Demo 分析
  9. 制作Ubuntu20.04系统盘
  10. Linux服务器集群系统(三)