(蓝桥杯第二课)递归原理与构造技巧

1、振兴中华

     小明参加了学校的趣味运动会,其中的一个项目是:跳格子。 

    地上画着一些格子,每个格子里写一个字,如下所示: 

    从我做起振 
    我做起振兴 
    做起振兴中 
    起振兴中华 

    比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。 

    要求跳过的路线刚好构成“从我做起振兴中华”这句话。请你帮助小明算一算他一共有多少种可能的跳跃路线呢?

这里写图片描述
此题的解法就是建立一个坐标系,如下图:
这里写图片描述

public class ZhenXingChina {

    /**
     * 振兴我大中华
     */

    static int f(int x, int y){
        if (x == 1 || y == 1) {
            return 1;
        }
        return f(x-1, y) + f(x, y-1);
    }
    public static void main(String[] args) {
        System.out.println(f(5,4));
    }
}

2、趣味算式

    匪警请拨110,即使手机欠费也可拨通!
    为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练!
    某批警察叔叔正在进行智力训练:
    1 2 3 4 5 6 7 8 9 = 110;
    请看上边的算式,为了使等式成立,需要在数字间填入加号或者减号(可以不填,但不能填入其它符号)。之间没有填入符号的数字组合成一个数,例如:12+34+56+7-8+9 就是一种合格的填法;123+4+5+67-89 是另一个可能的答案。
    请你利用计算机的优势,帮助警察叔叔快速找到所有答案。
    每个答案占一行。形如:
    12+34+56+7-8+9
    123+4+5+67-89
public class QuWei {

    /**
     * 趣味算式
     */


    /**
     * @param a 表示参加运算的元素
     * @param k 表示考虑的元素的下标
     * @param so 代表结果串
     * @param goal 代表计算目标
     */
    static void f(int a[], int k, String so, int goal){
        /*
         * 一共有3种选择
         */


        //跳出递归的条件
        if(k == 0){
            if (goal == a[k]) {
                System.out.println(a[k]+so);
            }
            return;
        }

        /*
         * 每次将新串加载合成结果的前面
         */
        f(a,k-1,"+"+a[k]+so,goal-a[k]);
        f(a,k-1,"-"+a[k]+so,goal+a[k]);
        int old = a[k-1];
        /*
         * 将两个数字进行合成。
         */
        a[k-1] = Integer.parseInt(""+a[k-1]+a[k]);
        f(a, k-1, so, goal);
        a[k-1] = old;    //回溯!!!

    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        /*
         * 递归的难点在于怎么设计递归方法的参数
         * 比如对于9老说,9的卡米面为+,-,或者与8合并
         */
        int a[] = {1,2,3,4,5,6,7,8,9};
        /*
         * a为当前运算的数字
         * s代表数组下标,下标从0开始
         * 如果从1开始时不太方便
         * 空串味积累好的算是
         * 110为计算的目标
         */
        f(a,8,"",110);
    }

}

运行结果如下:
这里写图片描述

3、车票找零

公园票价为5角。假设每位游客只持有两种币值的货币:5角、1元。 
再假设持有5角的有m人,持有1元的有n人。 
由于特殊情况,开始的时候,售票员没有零钱可找。 
我们想知道这m+n名游客以什么样的顺序购票则可以顺利完成购票过程。 
显然,m < n的时候,无论如何都不能完成; 
m >= n的时候,有些情况也不行。比如,第一个购票的乘客就持有1元。 
请计算出这m+n名游客所有可能顺利完成购票的不同情况的组合数目。 
注意:只关心5角和1元交替出现的次序的不同排列,持有同样币值的两名游客交换位置并不算做一种新的情况来计数。
import java.util.Scanner;

public class CarTicket {

    /**
     * 车票找零
     */

    /**
     * @param m 5角持有人数
     * @param n 1元持有人数
     */
    static int f(int m, int n){
        if(m<n) return 0;
        if(m == 1)   
            return 1;
        if (n == 1) {
            return 1;
        }
        return f(m-1, n) + f(m, n-1);
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner cin = new Scanner(System.in);
        int m = cin.nextInt();
        int n = cin.nextInt();
        System.out.println(f(m,n));
        cin.close();
    }

}

4、第39级台阶

小明刚刚看完电影《第39级台阶》。离开电影院的时候,他数了数礼堂前的台阶数,恰好是39! 站在台阶前,他突然又想着一个问题: 
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢? 
请你利用计算机的优势,帮助小明寻找答案。
public class Stair {

    /**
     * 第39级台阶
     */
    public static int count = 0;

    /**
     * @param stair 未走的楼梯层数,当n=0时,可结束递归。
     * @param step 累计 所走过的步数。
     */


    static void f(int stair, int step){
        //需要注意的是:当走到了只剩了一个台阶的时候,想要走两步是不可能的,因此需要进行递归返回。
        if(stair < 0){
            return;
        }
        if(stair == 0){
            if (step % 2 == 0) {
                count++;
            }
            return;
        }

        f(stair - 1, step+1);
        f(stair - 2, step+1);
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        f(39,0);
        System.out.println(count);
    }

}

答案:

51167078

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值