【C++】递归 -- 母牛生子问题

问题描述

某农场有一头刚出生的小奶牛,从第四个年头开始每年生一头母牛。之后的每一年大奶牛都会生一只小奶牛,而每过四年小奶牛就会长成大奶牛,长成大奶牛后又可以生小奶牛。请问 N 年后,此农场一共有多少头牛?

问题分析

这种问题就是典型的递推问题。

我们先搞懂题目意思:从第四个年头开始,即每过三年小母牛就长大成大奶牛,并在第四年年初产下一头小母牛。依次递推。

我们再来看下母牛有几种状态:一岁小奶牛、两岁小奶牛、三岁小奶牛、四岁及以上大奶牛(以下简称为大奶牛),前三种无产仔能力,后一种每年都可产下一头小奶牛。

之后,每过一年,上述每种奶牛的个数就会往后推进,即,两岁的个数为去年一岁个数、三岁的个数为去年两岁的个数、大奶牛的个数为去年三岁的个数加上去年大奶牛的个数,而一岁奶牛的个数同样为为去年三岁奶牛的个数加上去年大奶牛的个数。

设第 N 年奶牛总数为 S ,且 S = S(小) + S(大),即小奶牛加大奶牛。

这样一轮回之后我们可以发现,去年所有奶牛加起来刚好等于今年小奶牛的数量,即:S(小) = S(N - 1)

接下来,只要再把 S(大) 也用 N 来表示出来就得到了 S(N) 的递推公式了!

那么大奶牛应该如何表示呢?和往年的奶牛数量有什么关系呢?让我们换个角度想想,今年的大奶牛都是从哪里来的?

我们可以这样说:是三年前所有的牛牛变过来的,为什么这样说?因为三年前的牛无论大奶小奶(误,大牛小牛)到今年都会成大奶牛,且在这期间没有其他的大奶牛产生,因为三年前之后所产的仔到今年只能长成一岁、两岁或三岁。因此我们得到了:S(大) = S(N - 3)

综上,第 N 年奶牛的数量的递推公式为:S(N) = S(N-1) + S(N-2)

递推公式出来后,写函数就简单了,首先看看从第几年开始递推。在前三年,我们的祖先奶牛处于发育阶段,奶牛总数一直为1只,从第四年开始,开始出现了大奶牛和小奶牛,小奶牛继续发育,大奶牛每年继续产仔,因此,第四年就可以开始了递归。用C++编写函数即为:

int cowNum(int N)
{
	if(N == 1 || N == 2 || N ==3)
    {
     	return 1;   
    }
    else
    {
        return cowNum(N - 1) + cowNum(N - 3);
    }
}

来用一下:

#include <stdio.h>
#include <iostream>
using namespace std;

int cowNum(int year);

int main()
{
	cout << "你想知道多少年后奶牛的个数?";
	int year;
	cin >> year;

	cout << year << "年后奶牛的个数为:" << cowNum(year) << endl;
	system("pause");
	return 0;
}

int cowNum(int N)
{
	if (N == 1 || N == 2 || N == 3)
	{
		return 1;
	}
	else
	{
		return cowNum(N - 1) + cowNum(N - 3);
	}
}

运行以下:

你想知道多少年后奶牛的个数?20
20年后奶牛的个数为:872
请按任意键继续. . .

寻找递归公式还有个笨方法,就是有限穷举,比如下面这样:

观察观察也能发现规律,但是了解递推公式背后的真正原因才是最重要的。


为什么我能搞那么明白?因为我看答案了,我一开琢磨了二十多分钟都没有头绪,但是通过对解题思路的剖析,让我更了解了递归的实现过程,这个过程我想才是最重要的。

毕竟我也是新手,没必要苛求自己独自从0到1能够把任何算法的思路和代码全部搞定,能做到这样的可以说是天才了,毕竟我们都是普通人。

永远不要怀疑自己的能力,别人可以,你一定也可以。只不过一切需要从点点滴滴做起,积累经验,千里之行始于足下!

参考视频:https://www.bilibili.com/video/BV14y4y1U7yy

  • 29
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值