一、基本概念

动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。

二、基本思想与策略

基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。

与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。

以上都过于理论,还是看看常见的动态规划问题吧!!!

三、常见动态规划问题

1、找零钱问题

有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。
给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。
测试样例:
[1,2,4],3,3
返回:2

解析:设dp[n][m]为使用前n中货币凑成的m的种数,那么就会有两种情况:

使用第n种货币:dp[n-1][m]+dp[n-1][m-peney[n]]

不用第n种货币:dp[n-1][m],为什么不使用第n种货币呢,因为penney[n]>m。

这样就可以求出当m>=penney[n]时 dp[n][m] = dp[n-1][m]+dp[n-1][m-peney[n]],否则,dp[n][m] = dp[n-1][m]

代码如下:

  1. <span style="font-size:18px;">import java.util.*;
  2. public class Exchange {
  3. public int countWays(int[] penny, int n, int aim) {
  4. // write code here
  5. if(n==0||penny==null||aim<0){
  6. return 0;
  7. }
  8. int[][] pd = new int[n][aim+1];
  9. for(int i=0;i<n;i++){
  10. pd[i][0] = 1;
  11. }
  12. for(int i=1;penny[0]*i<=aim;i++){
  13. pd[0][penny[0]*i] = 1;
  14. }
  15. for(int i=1;i<n;i++){
  16. for(int j=0;j<=aim;j++){
  17. if(j>=penny[i]){
  18. pd[i][j] = pd[i-1][j]+pd[i][j-penny[i]];
  19. }else{
  20. pd[i][j] = pd[i-1][j];
  21. }
  22. }
  23. }
  24. return pd[n-1][aim];
  25. }
  26. }</span>

2、走方格问题

有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。
给定一个矩阵map及它的行数n和列数m,请返回最小路径和。保证行列数均小于等于100.
测试样例:
[[1,2,3],[1,1,1]],2,3
返回:4

解析:设dp[n][m]为走到n*m位置的路径长度,那么显而易见dp[n][m] = min(dp[n-1][m],dp[n][m-1]);

代码如下:

  1. <span style="font-size:18px;">import java.util.*;
  2. public class MinimumPath {
  3. public int getMin(int[][] map, int n, int m) {
  4. // write code here
  5. int[][] dp = new int[n][m];
  6. for(int i=0;i<n;i++){
  7. for(int j=0;j<=i;j++){
  8. dp[i][0]+=map[j][0];
  9. }
  10. }
  11. for(int i=0;i<m;i++){
  12. for(int j=0;j<=i;j++){
  13. dp[0][i]+=map[0][j];
  14. }
  15. }
  16. for(int i=1;i<n;i++){
  17. for(int j=1;j<m;j++){
  18. dp[i][j] = min(dp[i][j-1]+map[i][j],dp[i-1][j]+map[i][j]);
  19. }
  20. }
  21. return dp[n-1][m-1];
  22. }
  23. public int min(int a,int b){
  24. if(a>b){
  25. return b;
  26. }else{
  27. return a;
  28. }
  29. }
  30. }</span>

3、走台阶问题

有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法。为了防止溢出,请将结果Mod 1000000007
给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。
测试样例:
1
返回:1

解析:这是一个非常经典的为题,设f(n)为上n级台阶的方法,要上到n级台阶的最后一步有两种方式:从n-1级台阶走一步;从n-1级台阶走两步,于是就有了这个公式f(n) = f(n-1)+f(n-2);

代码如下:

  1. <span style="font-size:18px;">import java.util.*;
  2. public class GoUpstairs {
  3. public int countWays(int n) {
  4. // write code here
  5. if(n<=2)
  6. return n;
  7. int f = 1%1000000007;
  8. int s = 2%1000000007;
  9. int t = 0;
  10. for(int i=3;i<=n;i++){
  11. t = (f+s)%1000000007;
  12. f = s;
  13. s = t;
  14. }
  15. return t;
  16. }
  17. }</span>

4、最长公共序列数

给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最长公共子序列。
给定两个字符串A和B,同时给定两个串的长度n和m,请返回最长公共子序列的长度。保证两串长度均小于等于300。
测试样例:
"1A2C3D4B56",10,"B1D23CA45B6A",12
返回:6

解析:设dp[n][m] ,为A的前n个字符与B的前m个字符的公共序列长度,则当A[n]==B[m]的时候,dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]),否则,dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);

代码如下:

    1. <span style="font-size:18px;">import java.util.*;
    2. public class LCS {
    3. public int findLCS(String A, int n, String B, int m) {
    4. // write code here
    5. int[][] dp = new int[n][m];
    6. char[] a = A.toCharArray();
    7. char[] b = B.toCharArray();
    8. for(int i=0;i<n;i++){
    9. if(a[i]==b[0]){
    10. dp[i][0] = 1;
    11. for(int j=i+1;j<n;j++){
    12. dp[j][0] = 1;
    13. }
    14. break;
    15. }
    16. }
    17. for(int i=0;i<m;i++){
    18. if(a[0]==b[i]){
    19. dp[0][i] = 1;
    20. for(int j=i+1;j<m;j++){
    21. dp[0][j] = 1;
    22. }
    23. break;
    24. }
    25. }
    26. for(int i=1;i<n;i++){
    27. for(int j=1;j<m;j++){
    28. if(a[i]==b[j]){
    29. dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]);
    30. }else{
    31. dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
    32. }
    33. }
    34. }
    35. return dp[n-1][m-1];
    36. }
    37. public int max(int a,int b,int c){
    38. int max = a;
    39. if(b>max)
    40. max=b;
    41. if(c>max)
    42. max = c;
    43. return max;
    44. }
    45. }</span>

动态规划算法(后附常见动态规划为题及Java代码实现)的更多相关文章

  1. JVM组成、GC回收机制、算法、JVM常见启动参数、JAVA出现OOM,如何解决、tomcat优化方法

    JVM组成.GC回收机制.算法.JVM常见启动参数.JAVA出现OOM,如何解决.tomcat优化方法

  2. 排序算法对比,步骤,改进,java代码实现

    前言 发现是时候总结一番算法,基本类型的增删改查的性能对比,集合的串并性能的特性,死记太傻了,所以还是写在代码里,NO BB,SHOW ME THE CODE! github地址:https://gi ...

  3. 多线程动态规划算法求解TSP(Traveling Salesman Problem) 并附C语言实现例程

    TSP问题描述: 旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须 ...

  4. 动态规划算法(Dynamic Programming,简称 DP)

    动态规划算法(Dynamic Programming,简称 DP) 浅谈动态规划 动态规划算法(Dynamic Programming,简称 DP)似乎是一种很高深莫测的算法,你会在一些面试或算法书籍 ...

  5. 动态规划算法详解 Dynamic Programming

    博客出处: https://blog.csdn.net/u013309870/article/details/75193592 前言 最近在牛客网上做了几套公司的真题,发现有关动态规划(Dynamic ...

  6. 算法导论——lec 11 动态规划及应用

    和分治法一样,动态规划也是通过组合子问题的解而解决整个问题的.分治法是指将问题划分为一个一个独立的子问题,递归地求解各个子问题然后合并子问题的解而得到原问题的解.与此不同,动态规划适用于子问题不是相互 ...

  7. 以计算斐波那契数列为例说说动态规划算法(Dynamic Programming Algorithm Overlapping subproblems Optimal substructure Memoization Tabulation)

    动态规划(Dynamic Programming)是求解决策过程(decision process)最优化的数学方法.它的名字和动态没有关系,是Richard Bellman为了唬人而取的. 动态规划 ...

  8. 五大常用算法之二:动态规划算法(DP)

    一.基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 二.基本思想与策略 基本 ...

  9. 『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)

    本文索引目录: 一.动态规划的基本思想 二.数字三角形.最大子段和(PTA)递归方程 三.一道区间动态规划题点拨升华动态规划思想 四.结对编程情况 一.动态规划的基本思想: 1.1 基本概念: 动态规 ...

随机推荐

  1. css float 浮动是个混球

    得说,在学习 CSS 的时候就一直在疑惑,横排布局干嘛要用 float 这种属性, 用了还会高度塌陷,怎么不发明些高级点的属性来完成横排布局呢, 甚至所有人都告诉我摒弃表格布局,浮动布局才是 DIV+ ...

  2. MongoDB命令语法小用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using MongoDB; ...

  3. 2.3UML建模之用例图关系

    一.UML简介 UML(统一建模语言,Unified Modeling Language)是一种定义良好.易于表达.功能强大且普遍适用的可视化建模语言.它融入了软件工程领域的新思想.新方法和新技术.它 ...

  4. 大话设计模式之PHP篇 - 策略模式

    什么是策略模式? 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 组成:抽象策略角色: 策略类,通常由一个接口或者抽象 ...

  5. windows环境下安装部署并启用zkui的web图形界面

    在此之前的工作:不是本机部署的三个服务器最为伪集群的zookeeper环境,并将三个为服务启动起来. 然后才有了下面的工作. 1. 首先,zkui项目地址:https://github.com/Dee ...

  6. C++逗号表达式

    c++中,逗号表达式的结果是最右边表达式的值

  7. streambase log(log4j和logback)

    需要注意的是:当streambase servce 由window service 方式启动时,logback日志机制就不起作用了需要做下配置处理 https://support.tibco.com/ ...

  8. java中的特殊有用类

    1.MessageDigest:类似与md5加密算法应用的功能类

  9. 创建SVN仓库的步骤

    今天在客户现场联调,两个开发人员之间的代码想用SVN来管理,所以就临时在本地机器上搭建一个SVN仓库.现将操作步骤记录下来,以便后续查阅. 1.安装SVN服务端Setup-Subversion-1.6 ...

  10. 解决:TypeError: 'list' object is not callable

    如果list变量和list函数重名,会有什么后果呢?我们可以参考如下代码: list = ['泡芙', '汤圆', '鱼儿', '骆驼'] tup_1 = (1, 2, 3, 4, 5) tupToL ...