引子:在jillzhang那里看到大牛小牛问题,觉得很有趣,回去研究分析一下,发现很好玩。
问题:
一只刚出生的小牛,4年后生一只小牛,以后每年生一只。现有一只刚出生的小牛,问20年后共有牛多少只?
研究完,发现这是一个变形的Fibonacci数列。
首先,要分清楚第一年和1年后是不同的。第一年等于0年后,所以条件是4年后即第五年生一只小牛。
注意,这个条件理解不一样可是会得出不同的结果的。
设n年后,牛共有S(n)头则可以推出:S(n)=S(n-1)+S(n-4)。
推导过程如下:
n年后的牛的年龄为n岁,设0,1,2,3岁的牛(均为无生育能力)的个数分别为a(n),b(n),c(n),d(n),大于等于4岁的牛的个数为k(n)。注意:这里0岁指小牛刚出生。
则n年后S(n)=k(n)+a(n)+b(n)+c(n)+d(n)----------------------等式1
则n+1年后
0岁的小牛个数d(n+1)=k(n+1) //注意这里:事实上,1年后包括刚到4岁的牛都会立即生下一个小牛。
1岁小牛个数为c(n+1)=d(n)
2岁小牛个数为b(n+1)=c(n)
3岁小牛个数a(n+1)=b(n)
大于等于4岁的牛的个数为k(n+1)=k(n)+a(n)
总牛数:S(n+1)=k(n+1)+a(n+1)+b(n+1)+c(n+1)+d(n+1)
=(k(n)+a(n))+b(n)+c(n)+d(n)+k(n)+a(n)=S(n)+k(n)+a(n)
所以 k(n)+a(n)=S(n+1)-S(n)=k(n+1)由此
k(n)=S(n)-S(n-1)
所以
d(n)=k(n)=S(n)-S(n-1)
c(n)=k(n-1)=S(n-1)-S(n-2)
b(n)=k(n-2)=S(n-2)-S(n-3)
a(n)=k(n-3)=S(n-3)-S(n-4)
上面各式相加有: a(n)+b(n)+c(n)+d(n)=S(n)-S(n-4)
a(n)+b(n)+c(n)+d(n)=S(n)-k(n) (有等式1可得)
故k(n)=S(n-4)=S(n)-S(n-1)
所以S(n)=S(n-1)+S(n-4)
上面格式相加有S(n)=S(n-1)+S(n-4)
S(n)=S(n-1)+S(n-4), (n>=4) 其中S(0)=S(1)=S(2)=S(3)=1
程序实现(递归算法):
public static int getCount(int y)
{
if (y < 4)
{
return 1;
}
else
{
return getCount(y - 1) + getCount(y - 4);
}
}
递推算法:
public static int getCountEasy(int y)
{
int[] a = new int[5] { 1, 1, 1, 1,0 };
if (y < 4)
{
return 1;
}
else
{
for (int i = 4; i < y+1; i++)
{
a[4] = a[3] + a[0];
a[0] = a[1];
a[1] = a[2];
a[2] = a[3];
a[3] = a[4];
}
return a[4];
}
}
20年后的运行结果:
递归算法 Time:0ms Numbers:345
递推算法Time:0ms Numbers:345
60年后的运行结果:
递归算法 Time:4023ms Numbers:136886433
递推算法Time:0ms Numbers:136886433