1. 程式人生 > >1019: [SHOI2008]漢諾塔

1019: [SHOI2008]漢諾塔

center 就是 bre 第一個 cstring long 字符 pan 步驟

Time Limit: 1 Sec Memory Limit: 162 MB
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

3
AB 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]漢諾塔