連接:7×7 Skyscrapersjava
C#答案(緣由:懶,可是徹底能夠轉成C++):bajdcc/learnstlgit
題目(機翻):github
在7乘7格的網格中,你只想在每一個廣場上放置一個摩天大樓,只有一些線索:數組
你能寫一個能解決這個難題的程序嗎?函數
舉個例子,6x6的:測試
6x6 摩天大樓 例優化
(有人說看不懂規則3和4,我就以圖來講明一下)3d
我根據上圖製做了一個假城市(bajdcc/UnityTest),以下:code
咱們看線索中的左側(3,4,4):
輸入:int[]
輸入的數組下標
輸出:int[][]
花了兩天思考這個系列的問題,最終固然是寫出來了(光想沒用)。
這個題目感受跟數獨很像,我最早想的思路就是一步步推理,直到解決問題,然而,4x4大小的推理規則在6x6大小的問題中,可能須要補充一些東西或有些東西不實用了,這就麻煩了。
老實說,作數獨題的時候,我不怎麼用窮舉法,我是對當前局面進行推理,利用排除法一步步肯定答案,但用代碼實現推理就變得困難了,雖然這樣作是最優的(由於根據不作多餘計算)。
推理不能用,那就老老實實用窮舉法吧,雖然窮舉法有點low,但只要能過就行。
題目中透露了一些可供優化的信息:各行各列中數是惟一的。這就意味着複雜度從O(n^n)降低到O(n!)。這跟八皇后有點像,但又有所不一樣,所以我就用回溯法作。
肯定用回溯作,也感受能夠借鑑八皇后的思路,還不能立刻開工,有幾個問題:
先解決全排列問題:抄了下https://github.com/bajdcc/jProlog/blob/master/src/com/bajdcc/rt/gen/array/RtNorepArray.java#L43 哈哈。
回溯的順序應該是怎樣呢?本身試嘍。
先生成全排列,而後計算從左邊向右看到的樓層數(假設爲Sky函數,Sky:=int->int),將結果存到字典中。
會發現,當n=7時,sky(7)=1,可能性最低,都算出來後,排序。
sky(7)<sky(6)<sky(5)<sky(1)<sky(4)<sky(3)<sky(2)
展開順序的話,我確定先找n=7的狀況的,由於這時的不肯定性最低(解只有一個),至關於能夠肯定一個格子的值了。
目前的思路是:找到值=7的數,就直接敲定一排解(1~7);再找值=6的數,這時答案不惟一,回溯;繼續找……
這樣運行程序的話,確定是耗時很長的,緣由是什麼?
咱們優化程序的目標是回溯時盡能夠減小回溯次數,那就必須在決定一個展開順序:先展開不肯定性小的,再展開不肯定性較大的。
有一種狀況,能夠減小不肯定性:若是一排格子的兩側都有數字(都不是零),那其實能夠將它們放到一塊兒回溯。例: 5 | x x x x x x x | 2,這樣能夠極大下降可能性。事實證實這樣作有一點效果。
思路有了:
注意點:
代碼比較囉嗦,460行,不貼了(別人寫得都很短簡直了)。