• 算法之动态规划(递推求解一)


    这篇博客主要讲的是动态规划入门,即动态规划的思想,并且再讲解动态规划的最简单的一个方法。

    首先,什么是动态规划?

      动态规划是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。其实就是分解问题,分而治之。可能这样说大家都不太理解,其实这个有点类似于数学中的递推公式。来举一个简单的例子,看下边这个题:

      N阶楼梯上楼问题:一次可以走两阶或一阶,问有多少种上楼方式。

      这就是动态规划就简单的一个列子。拿到这个题,大家是不是都有点迷,这个到底怎么做?是不是没有思路,那么按照动态规划思想,我们可以先分析下问题,每次都有两种跳法,分别是一阶或者两阶,那么如果当前是第n个台阶,那么跳法是不是是(n-1)台阶的跳法数加上(n-2)台阶的跳法数?如果划算成公式是F(n) =  F(n-1)+F(n-2)。F(n)代表第n阶台阶的跳法的数量。

      这不就相当于找到了一个递推公式,然后来进行计算。具体的代码实现如下(采用的是非递归):

    #include <stdio.h>    
         
    int main()    
    {    
            int i,N;    
            long long a[90];    
            while(~scanf("%d",&N))    
            {                 
                    a[1]=1;    
                    a[2]=2;    
                    for(i=3;i<=N;i++)    
                            a[i]=a[i-1]+a[i-2];    
                    printf("%lld\n",a[N]);    
            }    
                 
            return 0;    
                 
    }   

    下边再举一个列子来辅助理解:

      n封信放入n个信封,要求全部放错,共有多少种放法,记n个元素的错排总数为f(n)

      对于这个题,我们可以采用和上述一样的思路,我们是否要考虑下找一个类似的递推公式等来解决。思路如下:

      在任意一种错装方案中,假设n号信封里装的是k号信封的信,而n号信封里的信则装在m号信封里。我们按照k和m的等值与否将总的错装方式分为两类。  若k不等于m,交换n号信封和m号信封的信后,n号信封里装的恰好是对应的信,而m号信封中错装k号信封里的信,即除n号信封外其余n-1个信封 全部错装,其错装方式等于 F[n - 1],又由于m的n-1个可能取值,这类错装方式总数为(n - 1)* F[n - 1]。也可以理解为,在 n-1个信封错装的 F[n - 1]种方式的基础上,将n号信封所装的信与n - 1个信封中任意一个信封(共有 n-1 中选 择)所装的信做交换后,得到所有信封全部错装的方式数。另一种情况,若 k 等于 m,交换 n 号信封和 m 号信封的信后,n 号信封和 m 号信封里装的恰好是对应的信,这样除它们之外剩余的 n-2 个信封全部错装,其 错装方式为 F[n - 2],又由于 m 的 n-1 个取值,这类错装方式总数为(n - 1)* F[n - 2]。也可以理解为,在 n - 2 个信封全部错装的基础上,交换最后两个信封中的 信(n 号信封和 1 到 n-1 号信封中任意一个,共有 n-1 种选择),使所有的信封全部 错装的方式数。  综上所述,F[n] = (n - 1) * F[n - 1] + (n - 1) * F[n - 2]。这就是错排公式。

      具体代码如下:

    #include <stdio.h>
    Long long F[21]; //数值较大选用long long
    int main () {
      F[1] = 0;
      F[2] = 1; //初始值
      for (int i = 3;i <= 20;i ++)
        F[i] = (i - 1) * F[i - 1] + (i - 1) * F[i - 2]; //递推求得数列每一个数字
      int n;
      while (scanf ("%d",&n) != EOF) {
        printf("%lld\n",F[n]); //输出
      }
      return 0;
    }

      

      

  • 相关阅读:
    WebService基于SoapHeader实现安全认证
    js中SetInterval与setTimeout用法
    Fiddler 教程
    jQuery 的 serializeArray()、serialize() 方法
    Javascript中Array.prototype.map()详解
    MS DOS 命令大全
    Chrome的JS调试工具
    jquery插件之DataTables 参数介绍
    C#中的Params、ref、out的区别
    C#记录日志、获取枚举值 等通用函数列表
  • 原文地址:https://www.cnblogs.com/cmai/p/7581959.html
Copyright © 2020-2023  润新知