1. 程式人生 > >SHOI2008 漢諾塔

SHOI2008 漢諾塔

 

傳送門

 我真愛漢諾塔

 

雖說是道紫題,但仔細想想仍適用於基礎版本的漢諾塔的遞推思路:對於每個情況中的底盤,必須將其上方所有的盤都先挪走。

 

轉移到這道題上,即將每個底盤上的所有盤全部按當前最高優先順序操作挪走。

 

進一步簡化,把每個底盤上的所有盤當作一個盤,按照最高優先順序操作移動即可。

 

理論有了,接下來又是我們喜聞樂見的數學推導

 

這就是就是就是就是就是道數學題,跟國王遊戲一樣坑

 

 


 

 

用 long long定義遞推陣列sum【110】

 

只有一個盤的時候可以一步到位,sum【1】=1

 

有兩個盤子時,就需要開始考慮優先順序的問題:

 

因為所有盤從A柱出發,因此要先討論從A挪到B和C的優先順序

 

若是B優先於C,則挪動兩次後底盤和上面盤將分別處於C、B柱

 

若從B出發,C優先於A,則可一步到位,sum【2】=3

 

另一種情況下,即A優於C,上面盤會被挪回到A,底盤只能被挪到B,上面盤再挪到B,總共需要sum【2】=5

 

回到第五行,若C優先於B,則情況剛好相反,此為兩盤的挪動步驟

 

那麼三盤呢?必須求出陣列的前三個數才能遞推啊

 

我相信聰明機智的各位都能類比上述推法自己推出三盤的步驟,這裡就不寫了(學校作業要寫不完了),因為推導過程是完全一樣的。

 

 

 

 

 

那麼到這裡,資料基礎問題已經解決了再求個遞推式就完美了:(方法極其水但可行)

 

Let's 回想一下當初刷openjudge上遞推漢諾塔的式子,因為上面盤要挪動兩次,底盤挪動一次,我們可得出遞推式為 sum[i+1]=sum[i]*2+1

 

類比一下,在本題中,上面盤看作一個盤,要挪動的次數假設為x,底盤要挪動的次數假設為y,則遞推式為sum[i+1]=sum[i]*x+y

 

簡單手推兩組sum[i+1]和sum[i](i>3)的資料(千萬別推錯了),代入,用sum[2]和sum[3]表示求出的x和y的值即可(多試幾次總會寫出對的。。)

 

要注意的地方就是求兩盤和三盤時,必須保證推出的步驟數正確

其次最後匯出的遞推式會很很很長,最好用定義變數拆開表示,不然可能會崩

(就這兩地方導致我暴了4次零)

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 long long miaocannotsay[40];
 5 char x[4];
 6 int miaoa[3][3];
 7 int main()
 8 {
 9     int n;
10     cin>>n;
11     for(int i=0;i<6;i++)//讀入 
12     {
13         scanf("%s",x);;
14         miaoa[x[0]-'A'][x[1]-'A']=6-i;
15     }
16     
17     miaocannotsay[1]=1;
18     if(miaoa[0][1]>miaoa[0][2])//AB AC
19     {
20         if(miaoa[1][2]<miaoa[1][0])//BC<BA
21         {
22             miaocannotsay[2]=5;
23             miaocannotsay[3]=17;
24         }
25         else
26         {
27             if(miaoa[2][0]>miaoa[2][1])//CA>CB
28             {
29                 miaocannotsay[2]=3;
30                 miaocannotsay[3]=7;
31             }
32             else
33             {
34                 miaocannotsay[2]=3;
35                 miaocannotsay[3]=9;
36             }
37         }
38     }
39     else 
40     {
41     if(miaoa[2][1]<miaoa[2][0])//CB<CA
42     {
43      miaocannotsay[2]=5;
44      miaocannotsay[3]=17;
45     }
46     else
47     {
48 
49     if(miaoa[1][0]>miaoa[1][2])//BA>BC
50     {
51      miaocannotsay[2]=3;    
52      miaocannotsay[3]=7;
53     }
54     else
55     {
56      miaocannotsay[2]=3;
57      miaocannotsay[3]=9;
58     }
59 }
60 }
61     int m=(miaocannotsay[2]*miaocannotsay[2]-miaocannotsay[1]*miaocannotsay[3])/(miaocannotsay[2]-miaocannotsay[1]);
62     int k=miaocannotsay[2]-m;
63     for(int i=4;i<=n;i++)
64     miaocannotsay[i]=miaocannotsay[i-1]*k+m;
65     cout<<miaocannotsay[n];
66     return 0;
67 }

祝各位冬幕節快樂