zoukankan      html  css  js  c++  java
  • 【华为云社区】悟一下动态规划

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

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

    动态规划(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练习题分享

  • 相关阅读:
    Chrome cookies folder
    Fat URLs Client Identification
    User Login Client Identification
    Client IP Address Client Identification
    HTTP Headers Client Identification
    The Personal Touch Client Identification 个性化接触 客户识别
    购物车 cookie session
    购物车删除商品,总价变化 innerHTML = ''并没有删除节点,内容仍存在
    453
    购物车-删除单行商品-HTMLTableElement.deleteRow()
  • 原文地址:https://www.cnblogs.com/huaweicloud/p/11861251.html
Copyright © 2011-2022 走看看