题目大意
给定一排长度为N(0<N<=50)的方格,向里面填入a,b,c三个数。要求任何相邻的方格数字不能相同,且首尾两格也不能相同。问:N个格子有几种填数方法
方法一(玄学大法)
首先进行暴力循环求结果得:
1 : 3
2 : 6
3 : 6
4 : 18
5 : 30
6 : 66
7 : 126
考虑到每一个数字开头都一样这里除以三发现:
1 : 1
2 : 2
3 : 2
4 : 6
5 : 10
6 : 22
7 : 42
发现当n>3时有规律 f(n) = f(n-1) + f(n-2)*2
提交后发现AC了
发现AC了
AC了
???
这样对学习递归没有好处,我们再看看常规方法
方法二(普通な方法)
首先当只有一个格子的时候不需要顾忌规则,显然有三种方法
当有两个格子的时候显然有六种方法
当有三个格子的时候通过排列发现也有六种方法
我们来思考一下有四个格子会怎么样
我们先列举当N=3的一种状态: 012
如果要是加一个格子去填数字的话是不是只能填1呢?由于规则
但是让你去列举的话难道就只能列出这一种吗?0101,0102他不行吗?
但是为什么光从N=3里列不出来呢?
因为规则!!!
所以我们需要再从N=2去考虑一下。
我们看看N=2时的一种状态:01
给他加两个格子让他填数字的话可以怎么填呢?
上过高中数学的应该都懂吧?
第三个位置可以填 0,2,当填0的时候第四个位置可以填1或2,当填2的时候只能再填一个1。
一共三种填法。但是有一种却是与N=3时的填法重复了我们需要去掉一个
即得出结果 f(4) = f(3) + (3-1)f(2) 有人可能会疑惑:为什么要去除从状态N=2种得出来得一种而不是从状态N=3的呢?
假设我们去掉了从状态N=3来的那么结果变成了f(4) = 3f(2),归纳总结得
f(n) = 3*f(n-2) 你会发现只满足了上述这一种情况,故不正确。
所以你会发现结果还是f(n) = f(n-1) + f(n-2)*2
不过这是一次运用递归思想而得出得结论,和那种瞎猜不一样
上代码:
#include <cstdio>
#include <cstring>
long long int ans[52];
int n;
/*
1 : 3
2 : 6
3 : 6
4 : 18
5 : 30
6 : 66
7 : 126
*/
int main()
{
int i;
ans[1] = 3;
ans[2] = 6;
ans[3] = 6;
ans[4] = 18;//18
for(i=5;i<=50;i++)
{
ans[i] = ans[i-1] + 2 * ans[i-2];
}
while(scanf("%d",&n) != EOF)
printf("%lld\n",ans[n]*3);
//for(i=1;i<=50;i++)printf("%d : %lld\n",i,ans[i]);
return 0;
}