• 【华为云社区】悟一下动态规划


    程序 = 数据结构+算法。所以,不了解算法的程序猿不是一个合格的程序猿,对算法痴迷是程序员的基本职业修养。哈哈,按照惯例,先扯下淡。

    下面来一起看下什么是动态规划,以下绿色字来自百度百科:

    动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。1957年出版了他的名著Dynamic Programming,这是该领域的第一本著作。

    动态规划问世以来,在经济管理、生产调度、工程技术和最优控制等方面得到了广泛的应用。例如最短路线、库存管理、资源分配、设备更新、排序、装载等问题,用动态规划方法比用其它方法求解更为方便。

    虽然动态规划主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。

    动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。不象搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。因此读者在学习时,除了要对基本概念和方法正确理解外,必须具体问题具体分析处理,以丰富的想象力去建立模型,用创造性的技巧去求解。我们也可以通过对若干有代表性的问题的动态规划算法进行分析、讨论,逐渐学会并掌握这一设计方法。

    看完了吧,有点儿晕了吧,正常,谁看都晕,我们来通过实战感受一把吧:

    如下图所示一个金字塔,请选择一条路使得从塔顶和路走到塔底(不得回头哦,跟人生一样,没有后悔药卖的)一路所过数字之和最大。

    如何解决?

    可能的最简单的想法是从上到下,每一步都选下一步可选方案中的最优方案方案不就行了么。这就是所谓的贪婪算法的基本思想。但是这样的思路真的可以得到正确的答案么?最终得到的路线一定是最优的路线么?

    结论是末必。要知道每一步的局部最优未必是全局最优哦。就好比高中时,我们每个同学的梦想都是可以考上名牌大学,这当时在大家看来是下步路最优的选择了。然而,十年后再回聚首,就会发现当年没考上大学的同学未必与上过大学的同学混得差哦。三十年河西,三十年河东。这就是局部最优未必是全局最优最好的诠释了,好好回味一下。

    回到问题,注意到我们的题目毕竟跟我们的人生选择还是不一样的。我们所做的每一次人生选择大部分都是按照贪婪算法来的,原因就在于人生选择是一次性,只能不停的沿着一条路往前走到底,我们的可视范围仅限于我们下一步的选择。当然少数特别有选见的人,会看得更远一些,为了长远利益放弃当前利益,就如当年比尔盖茨放弃大学文凭辍学办公司一样。而对于我们这个金字塔的题目,哈哈,太easy了,完全不用那么究竟,因为我们是可以遍历的哦。所有的路都遍历一遍,熟优熟劣自然一目了然。

    但是.....如何遍历,这又是一问题。

    相信了解二叉树的你,看到题目中的图,提起遍历第一时间想到的就是二叉树递归遍历了吧。但是需要提醒你的是,有两个问题是需要考虑的哦,一个是复杂度,相对于图中的节点数n,初步估计约为o(2^(n^(1/2))),这也够受了的。另一个是调用栈,这个塔有多少层,调用栈就有多么的深,这也不是闹着玩的,小塔还搞得定,高塔就彻底完了。

    怎么办?继续分析!

    注意到,要想自上而下到达塔中的某个点,要么我们从塔中该点的上一层下来就只有两个选择。例如,想要到达10这个节点,那么只有要么从18下来,要么从9下来。也就是说最优路径要么经过18,要么经过9。我们把10看作是雇员,18和9看作是10的潜在老板,至于10要选择给哪个老板打工,那就看谁能提供更多的money了,至于这个money,18和9这两个老板是怎么搞来的,这才不是雇员10关心的呢,雇员只认money,这就是市场。也就是所谓的无后效性。(这里的money,就是我们之前提出的所经过的链路之上的所有数字之和,你懂的)。

    接下来,问题转化了,雇员10最多可以拿到多少money,取决于了18和9两个老板手里可以最多可以拿到多少money。而18,9相同于自己的上层老板而言,自己又于雇员了。同同样的分析过程。问题再次向上转化。

    整过过程就是这样了,正过来想,那我们只需要从上到下,依次计算出每个老板手里最多可以拿到多少资源就可以了。计算出了第n层塔中各个节点的最大链路和,第n+1层的也就马上计算出来了。

    示例代码如下:

    #include <stdio.h>
    #define MAX_SIZE (5)
    #define MAX_OF(A,B)  ((A)>(B)?(A):(B))
    int main()
    {
     int node[MAX_SIZE][MAX_SIZE] = {
          {9},
          {12,15},
          {10,6,8},
          {2,18,9,5},
          {19,7,10,4,16}
           };
     int money[MAX_SIZE][MAX_SIZE] = {0};
     int MaxMoney = 0;
     int i,j;
        money[0][0] = node[0][0];
     for(i = 1;i<MAX_SIZE;i++)
     {
         money[i][0] = money[i-1][0] + node[i][0];
         for(j = 1;j<i;j++)
      {
          money[i][j] = MAX_OF(money[i-1][j-1],money[i-1][j]) + node[i][j];
      }
      money[i][i] = money[i-1][i-1] + node[i][i];
     }
     
     MaxMoney = money[MAX_SIZE-1][0];
     for(i = 0;i<MAX_SIZE;i++)
     {
         MaxMoney = MAX_OF(money[MAX_SIZE-1][i],MaxMoney);
     }
     printf("Max link Value: %d
    ",MaxMoney);
        return 0;
    }

    最终计算结果为:59

    至于如何把具体链路打出来,留给大家拍砖顶贴了。

    以上就是所谓的动态规划思想,简单吧,再悟一下。

    算法最重要的是思想。思想是定的,应用的具体方法是活的,活学活用,才是王道。

    掌声响起来,哈哈。

    作者:张亮

    往期文章精选

    如果让你手写个栈和队列,你还会写吗?

    挑战10个最难的Java面试题(附答案)【上】

    javascript基础修炼(13)——记一道有趣的JS脑洞练习题

    【我的物联网成长记3】如何开发物联网应用?

    【HC资料合集】2019华为全联接大会主题资料一站式汇总,免费下载!

     对你没有看错!不到 10 行代码完成抖音热门视频的爬取!

    Python面试的一些心得,与Python练习题分享

  • 相关阅读:
    Windows Phone开发(29):隔离存储C 转:http://blog.csdn.net/tcjiaan/article/details/7447469
    Windows Phone开发(25):启动器与选择器之WebBrowserTask 转:http://blog.csdn.net/tcjiaan/article/details/7404770
    内存知识集
    牛人榜
    如何解决SQL Server 2000 中的连接问题(邹建)
    索引
    .net事件机制
    内核对象
    使用socket tcp实现通讯
    sql技巧
  • 原文地址:https://www.cnblogs.com/2020-zhy-jzoj/p/13165269.html
Copyright © 2020-2023  润新知