动态规划

刺骨的言语ヽ痛彻心扉 2022-07-29 11:46 215阅读 0赞
  1. 首先,动态规划不是一个特定的算法,它代表的是一种思想,一种手段
  2. 动态规划方法往往用于求解“最优化问题”,能用动态规划求解的问题的前提是问题具有“最优子结构性质”。
  3. 最优子结构性质:问题的最优解由相关子问题的最优解组合而成,而这些子问题可以独立求解。
  4. 动态规划的核心是“状态的表达”和“状态转移方程的建立”,状态的意义的确立直接关系到状态转移方程能否建立正确。
  5. 动态规划问题常用的有两种方法:
    a. “自底向上”的递推。利用“问题的最优解包含子问题的最优解”,由于是“自底向上”求解的,就是说子子问题的最优解已经确立,子问题的最优解就可以从这些子子问题的最优解中确定出来。递推的关键是边界和计算顺序。
    b. 记忆化搜索。它是按照“自顶向下”的顺序求解的。与分治法将问题划分为互不相交的子问题不同的是,动态规划用于子问题重叠的情况(不同的子问题具有公共的子子问题),这样就必须要解决“子问题重复计算”的问题,否则会做大量的重复计算,效率急剧下降(就是单纯的搜索,这也就是为什么搜索只能过动态规划问题的一部分测试点的的原因)。记忆化搜索仍按照搜索的过程求解问题,但在搜索的工程中会保存每个子问题的解(用一个数组或散列表)。当需要一个解时,先去检查是否保存过此解,有,直接返回,否则按通常方式计算,并加以保存。注意,搜索可以剪枝!!!

一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。
更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。
记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,

具体问题分析:

  1. 1002 数塔取数问题
  2. 基准时间限制:1 空间限制:131072 KB 分值: 5 难度:1级算法题 收藏 关注
  3. 一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值。
  4. 每次只能走到下一层相邻的数上,例如从第3层的6向下走,只能走到第4层的29上。
  5. 5
  6. 8 4
  7. 3 6 9
  8. 7 2 9 5
  9. 例子中的最优方案是:5 + 8 + 6 + 9 = 28
  10. Input
  11. 1行:NN为数塔的高度。(2 <= N <= 500)
  12. 2 - N + 1行:每行包括1层数塔的数字,第21个数,第32个数......第k+1k个数。数与数之间用空格分隔(0 <= A[i] <= 10^5)
  13. Output
  14. 输出最大值
  15. Input示例
  16. 4
  17. 5
  18. 8 4
  19. 3 6 9
  20. 7 2 9 5
  21. Output示例
  22. 28

分析:

1.确定状态: 把当前的位置(i,j)看成一个状态,定义状态(i,j)的指标函数d(i,j)为从(i,j)点出发时能得到的最大和(包括(i,j)本身)。在这个状态下,问题解为d(1,1)

  1. 确定状态转移方程:从格子(i,j)出发有两种决策。往左走,走到(i+1,j)之后需要求“从(i+1,j)出发能得到的最大和”这一问题,即d(i+1,j),同样的,往右走,到达(i+1,j+1)后需要求解d(i+1,j+1)这一问题。即状态转移方程为:d(i,j)=a(i,j) + Max{d(i+1,j),d(i+1,j+1)}。数据结构a用于存储输入数据。
  2. 具体实现

    //用递推来做,相当于一棵二叉树,先确定最底层,然后依次确定上一层,知道第一层。
    import java.util.Scanner;

    public class Main {

    1. public static void show(int n,int[][] nums){
    2. System.out.println("Output trangels:");
    3. for(int i=1;i<=n;i++){
    4. for(int j=1;j<=i;j++) System.out.print(nums[i][j]+" ");
    5. System.out.println();
    6. }
    7. }
    8. public static void main(String[] args) {
    9. // TODO Auto-generated method stub
    10. Scanner in = new Scanner(System.in);
    11. while(in.hasNext()){
    12. int n = in.nextInt();
    13. int[][] triangle = new int[n+10][n+10];
    14. int[][] dp = new int[n+10][n+10];
    15. for(int i=1;i<=n;i++){
    16. for(int j=1;j<=i;j++) triangle[i][j] = in.nextInt();
    17. }
    18. //最后一层,作为起始边界。
    19. for(int j=1;j<=n;j++) dp[n][j] = triangle[n][j];
    20. //向上递推
    21. for(int i=n-1;i>=1;i--){
    22. for(int j=1;j<=i;j++){
    23. dp[i][j] = triangle[i][j] + Math.max(dp[i+1][j], dp[i+1][j+1]);
    24. }
    25. }
    26. System.out.println(dp[1][1]);
    27. }
    28. }

    }

    //记忆化搜索
    import java.util.Arrays;
    import java.util.Scanner;

    public class Main {

    1. public static int n;
    2. public static int[][] dp , triangle;
    3. public static void show(int n,int[][] nums){
    4. System.out.println("Output trangels:");
    5. for(int i=1;i<=n;i++){
    6. for(int j=1;j<=i;j++) System.out.print(nums[i][j]+" ");
    7. System.out.println();
    8. }
    9. }
    10. //利用赋值语句的返回值是所赋的值这一特性,将保存dp[i][j]的工作合并到函数的返回语句中。
    11. public static int memorySearch(int i,int j){
    12. if(dp[i][j]!=-1) return dp[i][j];
    13. if(i==n) return triangle[i][j];//搜索到最后一层了
    14. else return dp[i][j] = triangle[i][j] + Math.max(memorySearch(i+1, j), memorySearch(i+1, j+1));
    15. }
    16. public static void main(String[] args) {
    17. // TODO Auto-generated method stub
    18. Scanner in = new Scanner(System.in);
    19. while(in.hasNext()){
    20. n = in.nextInt();
    21. triangle = new int[n+10][n+10];
    22. dp = new int[n+10][n+10];
    23. //状态-1,代表没有访问过!!
    24. for(int i=1;i<=n;i++) Arrays.fill(dp[i], -1);
    25. for(int i=1;i<=n;i++){
    26. for(int j=1;j<=i;j++) triangle[i][j] = in.nextInt();
    27. }
    28. int res = memorySearch(1, 1);
    29. System.out.println(res);
    30. }
    31. }

    }

note:

  1. 分析出问题的最优子结构性质
  2. 构造状态
  3. 确定状态转移方程
  4. 选用合适的方法求解

发表评论

表情:
评论列表 (有 0 条评论,215人围观)

还没有评论,来说两句吧...

相关阅读

    相关 动态规划

    一:概念: 和分冶法相似,不同之处在于前者是把问题划分为互不相交的子问题,而动态规划会出现子问题重叠的情况。通常用来求解最优化问题。。 基本步骤: ①:刻画一个最优

    相关 动态规划

    -------------------- 动态规划的设计思想 动态规划(DP)\[1\]通过分解成子问题解决了给定复杂的问题,并存储子问题的结果,以避免再次计算相同的结

    相关 动态规划

    1. 首先,动态规划不是一个特定的算法,它代表的是一种思想,一种手段 2. 动态规划方法往往用于求解“最优化问题”,能用动态规划求解的问题的前提是问题具有“最优子结构性质”

    相关 动态规划

    首先是概念:动态规划就是将原问题划分为简单的几个小问题(有点类似与分治法?但是分治法中的各个小问题是相互独立的,彼此之间不会产生影响,但是动态规划中所得的值和前面相关,当前的解

    相关 动态规划

    > 给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。例如,A=”1A2C3D4B56”,B=”B1D23CA45B6A”,”123456”或者”12C4B6”都是最

    相关 动态规划

    基本思想:     动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 区别:     与

    相关 动态规划

    等我有时间了,一定要把《算法导论》啃完,这本书的印刷质量实在太好了,就是烧脑子,滑稽。 适合应用动态规划求解的最优化问题应该具备两个要素: 最优子结构:一个问题的最优解包含

    相关 动态规划

     1.题目:最长递增子序列(Longest Increasing Subsequence) 问题描述: > 给定长度为N的数组A,计算A的最长单调递增的子序列(不一定连续)