1 回答

TA貢獻1869條經驗 獲得超4個贊
當在第一列之一發生回溯并且必須嘗試下一行時,該算法需要相當多的時間。將奇數 N 板與 N-1 板進行比較確實表明,偶數板的解決方案通常需要進行更多此類回溯/嘗試下一個處理。例如,N=19 的解的左上角如下所示:
1 0 0 0 0
0 0 0 1 0
0 1 0 0 0
0 0 0 0 1*
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
前五列中的這 5 個皇后很快找到,因為它們是第一個不與之前的皇后發生碰撞的皇后。顯然可以放置其他皇后而不必重新考慮前五個皇后。
對于 N=18,解決方案的同一角落如下所示:
1 0 0 0 0
0 0 0 1 0
0 1 0 0 0
0 0 0 0 0-
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 1*
注意標有減號的位置。這個看起來很有希望(就像 19 板一樣):它的調查需要相當長的時間才能得出無法正確放置其他皇后的結論。這種早期失敗的代價。
因此,19 板的解決方案比 18 板更快地找到。
請注意,27 的解決方案比 26 的解決方案花費的時間略多,盡管這并不重要:看起來時間復雜度是O(2 n ),因此要比較不同板尺寸的時間,最好在對數 Y 軸:
“work”表示函數safe執行的次數。
這種算法是否總是對偶數板花費相對更多的時間(與 N+1 板所需的時間相比)尚不清楚,但對于這幾個板尺寸,它似乎與該算法自然形成的騎士跳躍有關,開始從左上角。請注意,這種模式如何完美地適用于 5 號和 7 號棋盤:下一個皇后可以坐在而不干擾先前定位的皇后的第一個位置始終是解決方案的一部分。而對于 4 號和 6 號棋盤,甚至沒有任何解決方案在角落里有一個皇后,這是該算法的起點。
備擇方案
從程序員的角度來看這個問題,有一種補救方法可以(平均而言)消除差異:以不同(甚至隨機)的順序選擇列。事實證明,采用正常順序是獲得解決方案的效率較低的方法之一。
換檔選擇
該算法的一個簡單轉變,除非所有其他行都失敗,否則您不考慮前兩行,已經大大改變了統計數據:
在solve_help改變這個:
for i in range(N):
到:
for i in range(N):
i = (i + 2) % N
看看現在平均性能是如何提高的:log(work)/n的所有測量值都低于 1,除了 n=6。而且:現在更頻繁地查看 N 的奇數值。
隨機挑選
for i in random.sample(range(N), N):
以下是這樣一次隨機運行的結果:
比原始訂單更好的統計數據!當然,你會時不時地得到一個糟糕的統計數據,......因為它是隨機的。但平均而言,它的表現(好得多)。
其他非隨機順序的方式可能包括col
, 和N//2
不同的系數, 如i = (i + col*2 + N//2) % N
, ...等。但請參閱下面的最后評論。
其他備注
我將應用以下優化:跟蹤哪些行、前向“對角線”和后向“對角線”已被采用。您可以為此使用列表或集合。請注意,如果兩個單元格的坐標之和相等,則兩個單元格位于同一對角線上。后對角線上的單元格的共同點是它們的坐標差相等。這樣您就不必每次都在這些行中掃描“1”。
此外,board
可能只是列號列表。無需存儲所有這些零。僅保留用于顯示。
最后,有一些簡單的方法可以在線性時間內獲得解決方案。參見維基百科。
添加回答
舉報