題目大意
給定一排長度爲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;
}