码迷,mamicode.com
首页 > 其他好文 > 详细

猴子爬山问题-递归

时间:2021-03-16 11:53:16      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:int()   初始   public   https   备忘录   ret   使用   ann   exti   

一个顽猴在一座有k级台阶的山上爬山跳跃,猴子上山一步可跳1级或跳3级,试求顽猴上山的N级台阶有多少种不同的跳法;

1.递推设计:

这一问题实际上是一个整数有序可重复拆分问题;

试设置数组应用递推求解,设上k级台阶的不同跳法为f(k)种;

(1)、探求f(k)的递推关系;

假设:k=100;

上山最后一步到达第100级台阶,完成上山,共有f(100)种不同的爬法,到第100级之前位于哪一级呢?无非是位于第99级(上跳1级即到),有f(99)种;

或位于第97级(上跳3级即到),有f(97)种,于是:

  • f(100)=f(99)+f(97)
  • f(99)= f(98)+f(96)
  • f(97)= f(96)+f(94)
  • 依次类推

以此类推,一般地有递推关系:

  • f(k)=f(k-1)+f(k-3) (k>3)

(2)、确定初始条件:

  • f(1)=1,即1=1;

  • f(2)=1,即2=1+1(注意:跳法中不允许直接跳2级);

  • f(3)=2,即3=1+1+1,3=3;

(3)、实施递推;

根据以上递推关系与初始条件设置一重k(4~n)循环,循环外确定初始条件,循环内实施递推:

  • f[k]=f[k-1]+f[k-3],即可求出f(n);//与斐波那契数列的求解一样

此具体案例的递推设计比较简单,时间复杂度为O(n);

程序设计(Java):

 public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int k = sc.nextInt();
        System.out.println(recursion(k));
    }

    static int recursion(int k){
        //f(1)=1,即1=1;
        //f(2)=1,即2=1+1(注意:跳法中不允许直接跳2级);
        //f(3)=2,即3=1+1+1,3=3;
        if(k==1 || k==2){
            return 1;
        }
        if(k==3){
            return 2;
        }
        return recursion(k-1)+recursion(k-3);
    }

2.一般情形的分级递推:

把问题引申为爬山n级台阶,一步有m种跨法,具体一种跨法跳多少级均从键盘输入;

(1)、分级递推设计;

1)、设置两个数组;

爬山t级台阶的不同爬法为f(t),从键盘输入一步跨多少级的m个整数为x[i](i=1,2,……,m);

这里的整数x(1),x(2),……,x(m)(约定x(1)< x(2)<……< x(m)< n)为键盘输入,事前并不知道,因此不能在设计时简单地确定初始值f(x(1)),f(x(2)),……;

事实上,可以把初始条件放在分级递推中求取,应用多关系分级递推算法完成递推;

2)、确定f(t)的递推关系;

当t< x(1)时,f(t)=0,f(x(1))=1 (初始条件);

当x(1)< t<=x(2)时,第1级递推:f(t)=f(t-x(1));

当x(2)< t<=x(3)时,第2级递推:f(t)=f(t-x(1))+f(t-x(2));

===================================

一般的,当x(k)< t<=x(k-1),k=1,2,……,m-1,有第k级递推:

f(t)=f(t-x(1))+f(t-x(2))+……f(t-x(k));
当x(m)< t时,第m级递推:

f(t)=f(t-x(1))+f(t-x(2))+……+f(t-x(m));
当t=x(2),或t=x(3),……,或t=x(m)时,按上面递推求f(t)外,还要加上1,道理很简单,因为此时t本身即为一个一步到位的爬法,为此,应在以上递推基础上添加:

f(t)=f(t)+1 (t=x(2),x(3),……,x(m));

======================
所求的目标为:

f(n)=f(n-x(1))+f(n-x(2))+……+f(n-x(m));

==========================================

这一递推式是我们设计的依据;

3)、设x(m+1)的技巧;

在递推设计中可以把台阶数n记为数组元素x(m+1),这样处理是巧妙地,可以按相同的递推规律递推计算,简化算法设计,最后一项f(x(m+1))即为所求f(n);

最后输出f(n)即f(x(m+1))时必须把额外所添加的1减去;

注意:上述求解过程中存在重复计算某个值,可以画出递归树来看,可以使用备忘录或者table表去优化。

可参考:https://www.cnblogs.com/controller666/p/14520459.html   带备忘录的递归解法

优化代码:

  public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int k = sc.nextInt();
        System.out.println(recursion(k));
    }

    public static int recursion(int n) {
        int[] res = new int[n+1];
        //备忘录全初始化为-1
        for (int i = 0; i < n+1; i++) {
            res[i] = -1;
        }
        //等于0的情况返回就是0
        if (n == 0) {
            res[n] = 0;
            return 0;
        }
        //等于1或者2的情况就是1 并记录已计算过
        if (n == 1) {
            res[n] = 1;
            return 1;
        }
        if (n == 2) {
            res[2] = 1;
            return 1;
        }
        //等于3的情况就是2 并记录已计算过
        if (n == 3) {
            res[3] = 2;
            return 2;
        }
        //如果数组中的值不是-1,则说明计算过,则直接返回,不再重复计算
        if (res[n] != -1)
            return res[n];
        res[n] = recursion(n - 1) + recursion(n - 3);
        return res[n];
    }

 

猴子爬山问题-递归

标签:int()   初始   public   https   备忘录   ret   使用   ann   exti   

原文地址:https://www.cnblogs.com/controller666/p/14532091.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!