USACO 1.4 clocks 分析

Description就不囉嗦了,見USACO的題目地址吧

http://ace.delos.com/usacoprob2?a=GYKcgnGbqEV&S=clocks

Analysis

由於同一種方法轉4次相當於不轉,所以轉的方案數共有4^9種;

9個鐘的狀態也共有4^9種;

分別用1230來表示36912則最終狀態爲全0

 

枚舉:分別枚舉9種方案的使用次數,然後判斷是否可行,下面的這個程序給我了很多啓發

 

 

Breadth First Search

這是我做的方法,一開始沒有用位運算來加速,所有就用了一個結構來保存,第一次用了結構內聲明函數來計算hash值;

  

位運算加速BFS

後來看了NOCOW上的位運算的思路,“

這樣,它們對應的二進制數爲:000001010011。即,我們用三個位來記錄一個時鐘的狀態(爲什麼不用兩位?請思考)。

 

tick一個時鐘的時候,就給該位加上一,再用按位與的方法去除高位的1

 

令最高的三位爲時鐘A,最低的三位爲時鐘I,那麼:

 

數“57521883”用於清除每個時鐘狀態最高位的一(按位與)。

 

const long move[9] = {18911232, 19136512, 2363904, 16810048, 2134536, 262657, 36936, 73, 4617}

 

move[i]表示題述中的第i+1種方法

 

f[q]爲原狀態,比如用題述中的第k種方法,那麼可以寫成 f[q + 1] = (f[q] + move[k - 1]) & 57521883;

 

9個時鐘都回歸12點的時候,巧的是狀態f=0。這樣,判斷每個狀態f是否爲0,就知道是否求出可行解。

上述方法要想用C++的程序過是不太可行的(除非你用要麻煩一下,把一個數拆成9個去hash,但這樣就體現不出位運算的優勢了),因爲要開一個57521883大的BOOL數組,但在C++中空間分配至少是1個字節,BOOL的前7位是無用的0,所以大小達到了57521883/2^20 M = 54 M,如果能用1位來存貯,則使用54 / 8 M = 6.75 M,由於USACO評測系統給的內存只有16 M,所以就不行了,但用自己電腦測試還是可以的,速度比前一種方法快10%左右。

還要特別注意的是:<<+的優先級,比如 1 << 2 + 3 = ?,不是7,而是32,因爲 << 的優先級比 +/-

還有一種很強的數學方法,和解方程法;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章