有一面积为2xN(1< =N< =10)的地板,给定两种不同瓷砖:一种长度为1x2(可以横竖),另一种长度为2x2,数目不限。要将这个长度为N的地板铺满,一共有多少种不同的铺法?
每次铺砖时考虑的情况大致类似,所以可以用递归求解。根据最后剩余的列数,我们将本问题分成两种情况:
A:最后剩余一列,那么假设把这列去掉后,其铺砖情况与n-1时的情况一样,而加上后,也只有一种情况所以方法数位pave(n-1)
B:最后剩余两列,那么把这两列先去掉后和n-2的情况一样,加上这两列后一共有三种情况:1*2竖着放2列,1*2横着放,2*2直接填满。因为1*2竖着放和A情况重复,所以方法数为pave(n-2)*2
综上:方法总数=pave(n-1)+2*pave(n-2)
高精度防止超出内存和编译时间。
#include<iostream>
#include<vector>
#include <string>
using namespace std;
int max(int x, int y) {
if (x > y) {
return x;
}
return y;
}
string myAdd(string a, string b) //高精度加法
{
int n = max(a.size(), b.size()) + 1;
vector<int>ans(n, 0);//开辟一个足够存储结果的数组,结果的位数最多为 位数最多的那个数的位数加一(考虑进位)
int i = a.size() - 1, j = b.size() - 1, k = n - 1;//从个位开始通过模拟竖式进行大数加法
while (i >= 0 && j >= 0)//当两数均未加完时
{
ans[k--] = (a[i--] - '0') + (b[j--] - '0');//我们让我们的数组存储每一位相加的结果注意将字符串转为整型数字
}
//检测是否有某个数的高位未加完将其直接存入数组中
while (j >= 0)
{
ans[k--] = (b[j--] - '0');
}
while (i >= 0)
{
ans[k--] = (a[i--] - '0');
}
string c = "";//创建一个字符串去存储答案
for (i = n - 1; i>0; i--)//因为之前的竖式加每一位都没考虑进位所以我们从最后开始检查进位
{//因为是加法如果有进位最多也就进一
if (ans[i] >= 10)//如果大于10说明应该进位那么我们让此位减10它的高一位加1
{
ans[i] -= 10;
ans[i - 1]++;
}
c.insert(0, 1, ans[i] + '0');//处理后的结果转化为字符插入结果字符的首位
}
if (ans[0]>0)//检查最最高位是否大于0如果两数相加没有进位那么这一位就是0我们就不必存储它否则则放入字符串
{
c.insert(0, 1, ans[0] + '0');
}
return c;//返回答案
}
string f(int k)
{
if (k <= 0) return "0";
if (k == 1) return "1";
if (k == 2) return "3";
string sum="0", right="3", left="1";
int i = 0;
for (i = 3; i < k + 1; i++)
{
sum = myAdd(right, left);
sum = myAdd(sum, left);
left = right;
right = sum;
}
return sum;
}
int main()
{
int k;
while (cin >> k)
{
cout << f(k)<<endl;
}
return 0;
}