zoukankan      html  css  js  c++  java
  • 爬楼梯问题

    有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?

    一个可以运行的程序,解释在后边:

    #include "stdio.h"
    
    int f(int x){
    
    
    	if(x==1)
    
        return 1;
    
        if(x==2)
    
        return 2;
    
        return (f(x-1)+f(x-2));
    
    }
    
    	int main(){
    	
    	int n;
    	
    	scanf("%d",&n);
    	
    	printf("%d",f(n));
    	
    	return 0;
    
    }
    

    方法一,直接思考问题:

    设f(x)=【剩x阶时,迈楼梯的方法总数】。首先迈出第一步,如果一次迈一阶,剩下x-1阶,方法总数为f(x-1);如果一次迈两阶,剩下x-2阶,方法总数为f(x-2);这里f(x-1) f(x-2)都是我们不知道的。这里只是找出一个递推关系式。即f(x)=f(x-1)+f(x-2)。容易发现,f(1)=1,f(2)=2。

    方法二,抽象成数学问题,找出递推关系式:

    如果x为1时,只可以迈一步,共有一种方法。

    如果x为2时,可以一次迈一步,也可以一次迈两步,共有两种方法。

    如果x为3时,可以先1,后2;可以先2,后1;也可以1,1,1;共有三种方法。满足f(1)+f(2)。

    如果x为4时,1,1,1,1; 1,2,1; 1,1,2; 2,1,1; 2,2; 共有五种方法。满足f(2)+f(3)。

    ......

    发现规律:f(x)=f(x-2)+f(x-1);

    总结:

    做递归函数时,我们不妨先从较小的数开始做实验,找出潜在的数学规律,抽象成数学问题。【即找出递推关系式】。这样比直接思考问题要简单一些。

    一个楼梯有20级,每次走1级或两级,请问从底走到顶一共有多少种走法?

    分析:假设从底走到第n级的走法有f(n)种,走到第n级有两个方法,一个是从(n-1)级走一步,另一个是从第(n-2)级走两步,前者有f(n-1)种方法,后者有f(n-2)种方法,所以有f(n)=f(n-1)+f(n-2),还有f(0)=1,f(1)=1.

    递归编程实现

    程序1

    #include <stdio.h>
    
    int f(int n)
    
    {
    
        if(n==0 || n==1) return 1;
    
        else return f(n-1)+f(n-2);
    
    }
    
    int main()
    
    {
    
         printf("%d
    ",f(20));
    
         return 0;
    
    }
    

    现在来说说动态规划的基本思想

    动态规划的关键是发现子问题和怎么记录子问题,以上面的例子说明

    (1)对子问题可递归的求解,当n>1时,f(n)=f(n-1)+f(n-2);否则,f(1)=f(0)=1;

    (2)这些子问题是有重叠的,即求解某个问题时,某些子问题可能需要求解多次。例如求解f(5)时,f(2)就被求解了3次。

    在上面两个条件下,用动态规划的方式来求解会高效很多。就是把子问题记录下来,每个子问题只求解一次,从而提高了效率。

    程序2

    #include <stdio.h>
    
    int result[100];
    
    int f(int n)
    
    {
    
      int res;
    
      if(result[n]>=0) return result[n];
    
      if(n==0 || n==1) res=1;
    
      else res=f(n-1)+f(n-2);
    
      result[n]=res;
    
      return res;
    
    }
    
    int main()
    
    {
    
      int i;
    
      for(i=0;i<=20;i++)
    
        result[i]=-1;
    
      printf("%d
    ",f(20));
    
      return 0;
    
    }
    

    程序3

    #include <stdio.h>
    
    int f[100];
    
    int main()
    
    {
    	
    	  int i;
    	
    	  f[0]=1;
    	
    	  f[1]=1;
    	
    	  for(i=2;i<=20;i++)
    	
    	   f[i]=f[i-1]+f[i-2];
    	
    	  printf("%d
    ",f[20]);
    	
    	  return 0;
    
    }
    

    程序3是否让你想起了那个兔子繁殖的问题呢?

    小结一下

    动态规划,采用分治的策略,把求最优解问题分解为求若干子问题的最优解,记录子问题的解,化繁为简,很实用,也很高效。

  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/fazero/p/4494203.html
Copyright © 2011-2022 走看看