Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 634|回复: 0

[算法学习]学习常用算法之(7)动态规划

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-25 00:04:21 | 显示全部楼层 |阅读模式
    首先让我们看一个例子:
    例1:如下图有一个数字三角阵,请编一个程序计算从顶点至底的某处的一条路径,使该路径所经过的数字的和最大。每一步可沿左斜线向下或右斜线向下走。
               7
           5     3
        4     2    1
      2     1    3    7

        这个问题的实质实际上是一个有向图中最长路经问题,可以用经典的图论算法或者搜索来解决。

         考虑如何用搜索法来解这道题,从第一个点开始扩展,每次扩展2个可行节点,直到达到数字三角形的底部,从所有的可行路径中找出最优值,这样做的复杂度是o(2^n),当n很大的时候,普通的搜索法将不可行。

          观察发现,搜索的效率低下很大程度上是因为做了大量的重复运算,因为对于任何一个节点,从他开始向下拓展的最优值是确定的,这启发了我们应当充分利用之前的运算结果。  
      
       
       
         
       

         
       
      
    下面我们来进行深入的分析,假如已经走第I行第J列,此时最大累加和S[I,J], 应选S[I-1,J-1],S[I-1,J+1]中较大者再加上(I,J)处的值A[I,J],即下式

       S[I,J]=A[I,J]+MAX(S[I-1,J-1],S[I-1,J+1])

       所以我们可以从第一行开始,向下逐行推出每一处位置的最大累加和S,最后从底行的N个S中选出最大的一个即为所求,这种算法的复杂度为o(n^2),比较搜索法,已经大大的降低了,这种充分利用已经计算出结果的方法,就叫做动态规划。   通过上面的例子,我们对“动态规划”有了一个初步认识,它所处理的问题是一个“多阶段决策问题”。我们现在对一些概念进行具体定义:

    状态(State):
        它表示事物的性质,是描述“动态规划”中的“单元”的量。如例1中的每个节点(指节点处的最大值)都为单个的状态。

    阶段(Stage):
        阶段是一些性质相近,可以同时处理的状态集合。通常,一个问题可以由处理的先后次序划分为几个阶段。如例1中的问题,每一行若干节点组成一个阶段。一个阶段既可以包含多个状态,也可以只包含一个状态。描述各阶段状态的变量称为状态变量,例1中可用S[4 , j]来表示第四阶段(即第四行)走到第j列的最大值,即第四阶段状态变量。

    状态转移方程:
         是前一个阶段的状态转移到后一个的状态的演变规律,是关于两个相邻阶段状态的方程,是“动态规划”的中心。

    如例1中: S[I,J]=A[I,J]+MAX(S[I-1,J],S[I-1,J+1])

    决策(Decision):
        每个阶段做出的某种选择性的行动。它是我们程序所需要完成的选择。如例1中MAX(S[I-1,J],S[I-1,J+1])

    动态规划所处理的问题是一个“多阶段决策问题”,一般由初始状态开始,通过对中间阶段决策的选择,达到结束状态。这些决策形成了一个决策序列,同时确定了完成整个过程的一条活动路线(通常是求最优的活动路线) 从上面的讲解我们可以发现:动态规划并不像一种算法,而更像一种思考方式。 下面,我们来讨论动态规划的应用范围,要确定一个问题是否能用动态规划,需要考虑两个方面:

    一:最优子结构
    即一个问题的最优解只取决于其子问题的最优解,也就是说,非最优解对问题的求解没有影响。我们再来看一个问题:

    例二:
         有4个点,分别是A、B、C、D,相邻两点用两条连线,表示两条通行的道路,给出每条道路的长度。我们定义从A到D的所有路径中,长度除以4所得余数最小的路径为最优路径。求一条最优路径。
         很多初学者往往会认为这道题也可以采用动态规划的方法,但实际并不如此,考虑这种情况:
    假如A-B的两条道路分别为2,3,B-C的两条道路分别为1,4。如果采用动态规划,节点B的最优值为2,节点C的最优值2,但际上到达C的最优值应该是0,即3-1这条线路。
    也就是说,C的最优取值不是由B的最优取值决定的,其不具有最优子结构。

    由此可见,并不是所有的“决策问题”都可以用“动态规划”来解决。所以,只有当一个问题呈现出最优子结构时,“动态规划”才可能是一个合适的侯选方法。 二:无后效性
    即一个问题被划分阶段后,阶段I中的状态只能由阶段I-1中的状态通过状态转移方程得来,与其他状态没有关系,特别是与未发生的状态没有关系,这就是无后效性。 例三:对于一个由数字组成的二叉树,求由叶子到根的一条路径的数字和的最大值.
                7
              3  8
            8  1  0
         2   7  4  4
       4   5  2  6  5

    从上往下计算,对于每一点,只需要保留从上面来的路径中和最大的路径的和即可。
    因为在它下面的点只关心到达它的最大路径和,不关心它从那条路经上来的。

    程序:(为了省时间,数字输入部分省了)
    1. import java.util.Scanner;

    2. public class Test{
    3.   public static void main(String args[]){
    4.      int n=5;
    5.     int a[][]={{0,0,0,0,0,7,0,0,0,0,0},
    6.                {0,0,0,0,3,0,8,0,0,0,0},
    7.                {0,0,0,8,0,1,0,0,0,0,0},
    8.                {0,0,2,0,7,0,4,0,4,0,0},
    9.                {0,4,0,5,0,2,0,6,0,5,0}};
    10.     int s[][]=new int[5][11];  
    11.     s[0][5]=a[0][5];
    12.     for(int i=1;i< n;i++){
    13.      for(int j=1;j< 10;j++){
    14.        s[i][j]=Math.max(s[i-1][j-1],s[i-1][j+1])+a[i][j];
    15.      }
    16.     }
    17.     System.out.println("原始数据");
    18.     for(int i=0;i< n;i++){
    19.      for(int j=0;j< 11;j++){
    20.        System.out.printf("%-4d",a[i][j]);
    21.     }
    22.     System.out.println();
    23.    }
    24.    
    25.    System.out.println();
    26.    System.out.println("对应的最大路径");
    27.    for(int i=0;i< n;i++){
    28.      for(int j=0;j< 11;j++){
    29.        System.out.printf("%-4d",s[i][j]);
    30.     }
    31.     System.out.println();
    32.    }
    33.    System.out.println();
    34.    System.out.println("最长路径的值为:");
    35.     System.out.println(max(s[n-1]));

    36. }
    37.   public static int max(int b[]){
    38.     int max=b[0];
    39.    for(int i=1;i< b.length;i++){
    40.      if(b[i]>max) max=b[i];
    41.    }
    42.    return max;
    43. }
    44.      
    45. }
    复制代码
    运行结果:

      

      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/11/25/000421609.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 04:31 , Processed in 0.369901 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表