蓝桥杯未名湖边的烦恼
问题描述
每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。
每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
两个整数,表示m和n
输出格式
一个整数,表示队伍的排法的方案数。
样例输入
3 2
样例输出
5
数据规模和约定
m,n∈[0,18]
问题分析
第一种解题思路
每一个位置只可能排放借用鞋子的同学和还鞋子的同学,我们对队伍采用逆序排序。并且使用递归求解:
1、如果队伍前面借用鞋子的人数大于还鞋子的人数了,那么该队伍肯定不是一个解,因此直接返回0。
2、在1不满足的条件下,如果我们队伍前面没有借鞋子的同学了,那么我们直接返回1即可,因为所有还鞋子的同学无论怎么排列都是一种解。
3、在1、2不满足的条件下,当前位置只有可能是还鞋子的同学或者是借鞋子的同学,因此我们呢递归fun(n,m-1)+fun(n-1,m)即可。
4、最后返回递归值即可求解。
第一种解题代码
package lanqiaobei;
import java.util.Scanner;
/**
* 递归求值
* @author yangjieyu
1、如果队伍前面借用鞋子的人数大于还鞋子的人数了,那么该队伍肯定不是一个解,因此直接返回0。
2、在1不满足的条件下,如果我们队伍前面没有借鞋子的同学了,那么我们直接返回1即可,因为所有还鞋子的同学无论怎么排列都是一种解。
3、在1、2不满足的条件下,当前位置只有可能是还鞋子的同学或者是借鞋子的同学,因此我们呢递归fun(n,m-1)+fun(n-1,m)即可。
4、最后返回递归值即可求解。
*/
public class Main {
private int fun(int n,int m) {
if(n<m) return 0 ;
else if(m==0){
return 1;
}
return fun(n-1, m)+fun(n, m-1);
}
public static void main(String[] args) {
int n,m;
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
Main main1 = new Main();
System.out.println(main1.fun(n, m));
scanner.close();
}
}
第二种解题思路:
第一种解题思路是从队伍的最后面开始排队的,反过来思考,我们可以从队伍的最前面开始排队。
令排在前面的还鞋子的人数为a,排在队伍前面借鞋子的人数为b。
1、当我们的还鞋总人数m<借鞋总人数n或者a<b时,我们一定时返回0。
2、当1不满自时,如果我们的b =m 或者时 a = n 时 返回1。
3、当1、2不满足时,我们就该位置排还鞋子的同学或者时排借鞋子的同学 fun(a+1,b)+ fun(a,b+1)。
第二种思路解题代码:
import java.util.Scanner;
/**
* 递归求值
* @author yangjieyu
令排在前面的还鞋子的人数为a,排在队伍前面借鞋子的人数为b。
1、当我们的还鞋总人数m<借鞋总人数n或者a<b时,我们一定时返回0。
2、当1不满自时,如果我们的b =m 或者时 a = n 时 返回1。
3、当1、2不满足时,我们就该位置排还鞋子的同学或者时排借鞋子的同学 fun(a+1,b)+ fun(a,b+1)。
*/
public class Main {
private int n = 0,m = 0;
private int fun(int a,int b) {
//a队伍前面还鞋子的人数,b队伍前面借鞋子的人数
if(a<b||m<n) return 0;
else if(a==m||b==n) return 1;
return fun(a+1, b) + fun(a, b+1);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Main main1 = new Main();
main1.m = scanner.nextInt();
main1.n = scanner.nextInt();
System.out.println(main1.fun(0,0));
scanner.close();
}
}