sicily1029 Rabbit

题目链接:http://soj.sysu.edu.cn/1029

题目大意:刚开始是有一对成年兔子,每对成年兔子在一个月后生下一对小兔子,小兔子经过 m 个月后成长为成年兔子。给定兔子从小兔子成长为成年兔子所需要的时间 m 个月,问在 d 个月后兔子的总对数。假设在整个过程中没有兔子死亡。

例如:当 m = 2, d = 3 时,输入结果为 5。但是这里我有个问题一直没想明白,按照题目的意思刚开始是1对兔子,那一个月后应该是1对成年兔子和1对小兔子(这对小兔子才刚出生),两个月后应该是一对成年兔子(还是最开始的那对成年兔子)和一对一月大的小兔子(由上个月出生成长起来的)和一对刚出生的小兔子,此时总共是3对兔子。3个月后就有2对成年兔子(一对是刚开始的成年兔子,一对是由一月后的一月大的兔子成长起来的),一对是一月大的兔子,还有一对是刚出生的兔子,总共是4对兔子。但是题目却不是这样理解的,它的理解方式应该是这样的:刚开始是一对成年兔子,1月后就有一对成年兔子和一对小兔子,总共是2对兔子;两个月后就有两对成年兔子(上个月的小兔子已经变成成年兔子了。是兔子出生就默认一个月大呢还是兔子经过1个月就能成长为成年兔子?我还是没想明白)和一对小兔子,总共是3对兔子;三个月后就有3对成年兔子和2对小兔子,总共是5对兔子。先不管这些,就按题目的意思来解题吧。

解题思路:递推(也可以说是动态规划) + 高精度加法

递推:假设兔子经过 m 个月从小兔子成长为成年兔子,用 dp[i] 表示第 i 个月后兔子的总对数,那么有 dp[i] = dp[i - 1] + dp[i - m]。其中边界条件为:for i from 0 to m: dp[i] = i + 1.

高精度加法:如果只是上述的简单的递推的话,那用一个int一维数组存储数据也就完事了,但是本题中出现大数据超出int范围,于是不得不考虑用高精度加法。那么现在一维数组不能满足需求了,考虑平时到高精度加法都是把字符串转换为int数组存储然后再操作,这里就直接使用二维数组 int a[][]来表示,其中a[i][]表示第 i 个月后兔子总对数k,k 的每一位存在a[i][]中。

#include 
using namespace std;

int main()
{
	//  用二维数组存储每个数,i 个月后兔子总数存储在 a[i] 中
	//  a[i][j]表示 i 个月后兔子总数从右往左数第 110 - j 位的数字
	int m, d, a[110][110];
	while (1)
	{
		cin >> m >>d;
		if (m == 0 && d == 0)
			break;
		//  初始化
		for (int i = 0; i < 110; i++)
			for (int j = 0; j < 110; j++)
				a[i][j] = 0;
		for (int i = 0; i <= m; i++)
			a[i][109] = i + 1;
		//  递推
		for (int i = m + 1; i <= d; i++)
		{
			//  高精度加法
			for (int j = 109; j >= 0; j--)
			{
				a[i][j] += a[i - 1][j] + a[i - m][j];
				//  处理进位
				if (a[i][j] > 9)
				{
					a[i][j - 1] += a[i][j] / 10;
					a[i][j] %= 10;
				}
			}
		}
		//  输出结果,排除前面的 0
		for (int i = 0; i < 110; i++)
			if (a[d][i] != 0)
			{
				for (int j = i; j < 110; j++)
					cout << a[d][j];
				break;
			}
		cout << endl;
	}
	return 0;
}


你可能感兴趣的:(sicily)