1019: [SHOI2008]漢諾塔
阿新 • • 發佈:2018-06-21
center 就是 bre 第一個 cstring long 字符 pan 步驟 Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 1981 Solved: 1208
[Submit][Status][Discuss]
柱子B。漢諾塔的遊戲目標是將所有的盤子從柱子A移動到柱子B或柱子C上面。有一種非常簡潔而經典的策略可以幫
助我們完成這個遊戲。首先,在任何操作執行之前,我們以任意的次序為六種操作(AB、AC、BA、BC、CA和CB)
賦予不同的優先級,然後,我們總是選擇符合以下兩個條件的操作來移動盤子,直到所有的盤子都從柱子A移動到
另一根柱子:(1)這種操作是所有合法操作中優先級最高的;(2)這種操作所要移動的盤子不是上一次操作所移
動的那個盤子。可以證明,上述策略一定能完成漢諾塔遊戲。現在你的任務就是假設給定了每種操作的優先級,計
算按照上述策略操作漢諾塔移動所需要的步驟數。
作的優先級,靠前的操作具有較高的優先級。每種操作都由一個空格隔開。
AB BC CA BA CB AC
並由此得到兩個方程: k×f[1]+b=f[2] k×f[2]+b=f[3]
Submit: 1981 Solved: 1208
[Submit][Status][Discuss]
Description
漢諾塔由三根柱子(分別用A B C表示)和n個大小互不相同的空心盤子組成。一開始n個盤子都摞在柱子A上,
大的在下面,小的在上面,形成了一個塔狀的錐形體。
對漢諾塔的一次合法的操作是指:從一根柱子的最上層拿一個盤子放到另一根柱子的最上層,同時要保證被移
動的盤子一定放在比它更大的盤子上面(如果移動到空柱子上就不需要滿足這個要求)。我們可以用兩個字母來描
述一次操作:第一個字母代表起始柱子,第二個字母代表目標柱子。例如,AB就是把柱子A最上面的那個盤子移到
柱子B。漢諾塔的遊戲目標是將所有的盤子從柱子A移動到柱子B或柱子C上面。有一種非常簡潔而經典的策略可以幫
助我們完成這個遊戲。首先,在任何操作執行之前,我們以任意的次序為六種操作(AB、AC、BA、BC、CA和CB)
賦予不同的優先級,然後,我們總是選擇符合以下兩個條件的操作來移動盤子,直到所有的盤子都從柱子A移動到
另一根柱子:(1)這種操作是所有合法操作中優先級最高的;(2)這種操作所要移動的盤子不是上一次操作所移
動的那個盤子。可以證明,上述策略一定能完成漢諾塔遊戲。現在你的任務就是假設給定了每種操作的優先級,計
算按照上述策略操作漢諾塔移動所需要的步驟數。
Input
輸入有兩行。第一行為一個整數n(1≤n≤30),代表盤子的個數。第二行是一串大寫的ABC字符,代表六種操
作的優先級,靠前的操作具有較高的優先級。每種操作都由一個空格隔開。
Output
只需輸出一個數,這個數表示移動的次數。我們保證答案不會超過10的18次方。
Sample Input
3AB BC CA BA CB AC
Sample Output
7 可以類比normal漢諾塔得出遞歸規律f[n]=k×f[n-1]+b並由此得到兩個方程: k×f[1]+b=f[2] k×f[2]+b=f[3]
解得:
\[k=\frac{f[3]-f[2]}{f[2]-f[1]}\]
\[b=f[3]-f[2]*k\]
因此我們只需要搜索出f[1],f[2],f[3],就可以得出答案了,而f[1]=1是顯而易見的結論 這裏巧妙利用了stack的特性(這算是投機取巧吧(大霧)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<stack> 5 using namespace std; 6 7 #define LL long long 8 9 int n,x[10],y[10]; 10 char ch[10]; 11 LL k,b,f[50]; 12 13 int dfs(int t) 14 { 15 stack<int> A[3]; 16 int last=-1,ans=0; 17 for(int i=t;i>=1;i--) A[0].push(i); 18 while(A[1].size()!=t&&A[2].size()!=t) 19 for(int i=1;i<=6;i++) 20 if(A[x[i]].size()>0&&last!=x[i]) 21 { 22 int a=A[x[i]].top(),b=5; 23 if(A[y[i]].size()>0) b=A[y[i]].top(); 24 if(a<b) 25 { 26 A[x[i]].pop();A[y[i]].push(a); 27 last=y[i]; 28 ans++; 29 break; 30 } 31 } 32 return ans; 33 } 34 35 int main() 36 { 37 scanf("%d",&n); 38 for(int i=1;i<=6;i++) 39 { 40 cin>>ch; 41 x[i]=ch[0]-‘A‘; 42 y[i]=ch[1]-‘A‘; 43 } 44 f[1]=1;f[2]=dfs(2);f[3]=dfs(3); 45 k=(f[3]-f[2])/(f[2]-f[1]); 46 b=f[3]-f[2]*k; 47 for(int i=4;i<=n;i++) f[i]=f[i-1]*k+b; 48 cout<<f[n]<<endl; 49 return 0; 50 }
1019: [SHOI2008]漢諾塔