(完整代码在最下面)
题目描述:
有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
输入:
输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n<55),n的含义如题目中描述。n=0表示输入数据的结束,不做处理。
输出:
对于每个测试实例,输出在第n年的时候母牛的数量。
每个输出占一行。
样例输入:
2 4 5 0
样例输出:
2 4 6
首先看到题目已经明确了用递归(回溯)算法来做,当然用其他的也可以,根据题目描述理解,大概是开始只有一头母牛,然后每年都会以题中的规则增长母牛,求到最后牛总个数
增长规则:一头母球每年初生一头母牛,小母牛第四年初生一头母牛。
解题思路:
sum(n):第n年母牛的总数
year(n):第n年
1. 首先,按照我的思路是把题完全看了一遍,刚开始看到最后的输入输出还不理解什么意思,后来知道每个数代表经历多少年,以0结束,输出结果是对应年的母牛总数————以题中为例:
2 4 5 0 就是year(2),year(4),year(5),0代表此次输入结束
2 4 6 代表sum(2),sum(4)和sum(5)
2. 设计递归函数代码
我们已经知道母牛的增长规则了,包含了几种情况
①year == 1
②year > 1:
1)year <= 4
2)year > 4
为什么会有这几种情况,首先递归的一个基本思想先分类:把最简单(这里是year == 1)的情况分一类,把其他情况分一类(可能还需要继续细分,这里需要自己的经验判断了)。
然后我在纸上计算出了 sum(n) 其实不包括第n年出生的牛,而且从第4年开始每年就有小母牛会生崽,所以分为第四年前和第4年后的情况
下面开始编写代码:
①输入规则
我们已经知道了是循环输入的,直到0结束,所以输入的代码肯定要用循环来做而且sum(n)记录在数组或集合中
List<Integer> a = new ArrayList<Integer>();
Scanner scanner = new Scanner(System.in);
int year,sum = 0;
//year是获取输入的年——判断输入的年是否满足条件
//sum是年份对应的母牛个数
while(!(year = scanner.nextInt()) <= 0)){
sum = recursion(year);
a.add(sum);
}
小伙伴们应该可以看明白,如果year > 0就进入循环调用递归函数,之后把返回的sum结果添加到list集合中,搞定!
②递归实现
上面已经罗列了几种可能的情况,直接上代码
public static int recursion(int year){
if(year == 1 || year == 0){
return 1;
}else{
if(year <= 4){
return recursion(year - 1) + 1;
}else{
return recursion(year - 1) + recursion(year - 3);
}
}
}
其他代码不说,我们来分析分析进入else以后
① if ( year <=4 && year > 1 ) 这一年刚好没有小母牛生崽,所以直接调用recursion(year - 1) + 1,函数内的 - 1是要递归计算这几年所有出生的小母牛,总体加1是因为每年初母牛会生一个小母牛
② if ( year > 4 ) ,要考虑小母牛生崽的情况了,其实也不难,我们把刚开始的母牛递归,加上出生大于四年之后的小母牛递归情况,就把所有的母牛都考虑进来了。
1) 为什么递归小母牛要传入year - 3?
因为我们计算n年来出生的总数量,其实是不把第n年出生的小母牛计算在内的,所以计算的是n - 1年的母牛总和,所以year 减的是3而不是4。
2)为什么year > 4 的返回值不是 + 1 ?
+1原本就是为了表示这年比上年多生一个小母牛,这个有点难理解,可以理解为递归某一次recursion(n) + recursion(n-3)的时候会返回上一次递归母牛所有的数量(不包括递归小母牛的数量,但包括这年生的一个小母牛),所以就抵消了那个+1,也就是说两个递归的返回值已经包含了这年新生的小母牛了,所以把外面的+1去掉了,画思路图验证一下
我们要仔细想一下,递归母牛是为了计算母牛出生的崽子,那递归出生年>4的小母牛不也是计算小母牛出生的崽子嘛,好多小伙伴没想到小母牛也需要递归一下,这就导致了思路断片。
import java.util.Scanner;
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Integer> a = new ArrayList<Integer>();
Scanner scanner = new Scanner(System.in);
int year,sum = 0;
while(!((year = scanner.nextInt())<= 0)){
sum = recursion(year);
a.add(sum);
}
for(Integer x : a){
System.out.println(x);
}
}
public static int recursion(int year){
if(year == 1 || year == 0){
return 1;
}else{
if(year <= 4){
return recursion(year - 1) + 1;
}else{
return recursion(year - 1) + recursion(year - 3);
}
}
}
}
验证此算法是否正确的地址如下 → 母牛的故事
有问题欢迎在下方留言,侵删!