Problem Description
從三個元素的集合[A,B,C]中選取元素生成一個N個字符組成的序列,使得沒有兩個相鄰字的子序列(子序列長度=2)相同。例:N=5時ABCBA是合格的,而序列ABCBC與ABABC是不合格的,因為其中子序列BC,AB是相同的。
對於由鍵盤輸入的N(1<=N<=12),求出滿足條件的N個字符的所有序列總數。
對於由鍵盤輸入的N(1<=N<=12),求出滿足條件的N個字符的所有序列總數。
Input
輸入有多組數據,每組數據只有一行為一個整數N。
Output
Sample Input
4
Sample Output
72
關鍵是怎樣判斷相鄰的子序列不能相同,我們可以把A B C 三個字母相當於1 2 3,一開始我試試這樣想的,每加入一個數,就要看看這個數前面那個數的前面那個數(orz)與它是否相等,
如果相等計數器+1,當計數器加到2時說明有兩個子序列相同了,如12123(ABABC)第三個位置和第一個位置上都是1(A),計數器+1,第四個位置和第二個位置都是2(B)計數器+1,
此時計數器已經到2了所以這種情況舍棄///然后學長說ABACA這樣計數器也會到2啊,但是卻符合要求,我的方法的漏洞是我找到的是不連續的兩個子序列,所以一旦所加的位置的數和前兩位不一樣,計數器清零。(學長的方法:可以把每個字母用不一樣的素數代替,然后判斷時前面我們是*10,我們可以乘一個比較大的素數,比較和是否相等,素數與素數的和是很難相等的;)
(看不懂也沒關系,我表達的很爛‘’‘’‘’‘’學長講得很清楚)
接下來我說一下這個代碼的方法:例如12123(ABABC)每加入一個數(加入我們加入第四個位置的2吧)要計算第一個位置的數*10+第二個位置的數,和第三個位置上的數*10+我們正要加的數,這樣 十二和十二相等,說明這個情況我們要舍棄了。
【代碼】
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; int n,js,sum,ans[5]; void search(int); int main() { scanf("%d",&n); search(1); cout<<sum<<endl; return 0; } void search(int x) { for(int i=1; i<=3; i++) { ans[x]=i; if(x>3&&ans[x-3]*10+ans[x-2]==ans[x-1]*10+ans[x])//判斷子序列 continue; else { if(x==n)sum++; else search(x+1); } } }