【算法研究】數獨高效徹底解生成算法的研究和實現(轉)

對於數獨遊戲的研究,咱們難免要研究數獨遊戲的徹底解的生成算法,對於徹底解的生成過程,咱們通常是採用回溯法來產生整個九宮格的全部的數據。而對於九九八十一格的數獨遊戲完整解生成,咱們嘗試按常規的回溯方法來實現,難免會出現回溯的解空間過於龐大而致使回溯的時間過長而沒法知足遊戲中咱們產生遊戲徹底解的須要。爲此,咱們須要一種高效的徹底解的生成算法,以知足咱們在數獨遊戲中快速的產生徹底解。對此,咱們須要對數獨進行進一步的探索和研究。html

那首先咱們來了解一下數獨遊戲,數獨的基本規則就是在以下圖所示的大九宮格中的九九八十一格里隨機填入1-9這九個數字中的任意一個,而且要保證每一橫行、豎行的九個數字沒有重複數字,還要保證每個小九宮格中的九個數字也不能重複。以下圖,咱們將每個小九宮格塗上了不一樣的顏色以便於區分。java

【算法研究】數獨高效徹底解生成算法的研究和實現 

要生成合法的數獨徹底解,那咱們必須瞭解數獨徹底解的所具備的特性。那咱們下面看一組標準的數獨徹底解的例子,以下所示咱們看到一組數獨徹底解(這是咱們實現的算法生成的解)。算法

 8 7 1 9 3 2 6 4 5 測試

 4 9 5 8 6 1 2 3 7 url

 6 3 2 7 5 4 8 1 9 spa

 5 2 8 4 7 3 1 9 6 3d

 9 1 3 6 2 5 7 8 4 htm

 7 6 4 1 9 8 3 5 2 blog

 2 8 7 3 4 9 5 6 1 排序

 1 4 6 5 8 7 9 2 3 

 3 5 9 2 1 6 4 7 8 

經過檢查,咱們看到上面這一組解是知足數獨規則的。但咱們爲了研究數獨徹底解的特性,須要將這一組解放入九宮格中進行分析,以下圖咱們將這一組解放入到九宮格,首先咱們知道,整個大九宮格(九九八十一格)中咱們只能填入數字1-9,而咱們看到的是橫行、豎行和小九宮格都是九格,也就是說,咱們在橫行、豎行和小九宮格都必須使用到這九個數字。

    【算法研究】數獨高效徹底解生成算法的研究和實現

若咱們要生成一組數獨徹底解,那若是按傳統的回溯方法來產生,那咱們首先會從第一個方格(從左至右,從上至下)開始,先從1-9九個數字中選取一個數字填入該處,而後咱們再從第二個方格開始,選取八個數字(按數獨規則不能重複,則要除去剛剛填入的一個數字)中的一個,依此下去選填數字……固然後續方格中選擇的數字,都會由於數獨規則,使其所在橫行、豎行和小九宮格中,其餘已填方格中的數字對該處可填入的數字產生不一樣的條件約束。某種狀況下,咱們可能發現填到某格時,因爲數獨規則約束咱們已經沒有數字能夠填入該處了,這時候咱們就要開始回溯了,撤銷上一步填入的數字,從新選擇一個數字填入上一步的方格,而後繼續開始本次的填數,若不行還得繼續回溯。有時會由於某種制約,致使咱們要不停回溯撤銷重填。若按照這種思路作下去,咱們發現因爲解空間過於龐大,咱們能生成合適的徹底解可能要花比較長的時間。這樣的算法思路根本沒法知足咱們快速產生徹底解的須要。這時咱們想到要去縮小回溯的解空間,讓回溯的解空間儘可能的減少。

因而咱們開始的新的算法探索,以下圖經過分析咱們知道,1-9這九個數字必定都會被使用,並且是每一橫行、豎行和每個小九宮格都會有1-9中的一個數字。首先咱們來對整個大九宮格進行劃分,咱們將整個大九宮格劃分爲九個小九宮格。按從左至右,從上至下排序,也就是上面三個分別爲123中間三個分別爲456,而下面三個分別爲789。那咱們先填1-9這九個數字中的「1」,咱們觀察下面圖例的解能夠看到。在第一個小九宮格中填入一個「1」,在第2、三個小九宮格中也要填入一個「1」,而要知足數獨規則,第二個小九宮格中填入的「1」就不能和第一個小九宮格的「1」在同一行,同時第三個小九宮格填入的數字「1」也不能和第1、二個小九宮格的「1」在同一行。以此類推下去,咱們繼續填第4、5、6、7、8、九個小九宮格中的「1」,當第九個小九宮格數字「1」填完之後,整個過程徹底能夠不用回溯。那咱們接着開始填入1-9這九個數字中數字「2」,在第一個小九宮格中咱們除去以前填入數字「1」被佔用的位置,其餘的八個空的方格咱們都是能夠隨便填的,咱們隨機選取其中的一個空格,填入數字「2」。填完後,咱們接着填第二個小九宮格中的數字「2」,填入的位置要求仍是要知足數獨規則的,在這裏因爲咱們在每一個小九宮格中1-9中的每一個數字都填過一次,因此這裏徹底不用考慮小九宮格的數字不重複的問題,因此考慮的就是,每一橫行、豎行是否知足數獨規則,即填入的數字都不重複。這樣咱們按照必定的順序依次在九個小九宮格中填入1-9這九個數字。當九個小九宮格的數字「9」填完。整個大九宮格九九八十一個數字填入完畢,那麼符合數獨規則的徹底解也就應運而生。固然這裏也會有回溯的狀況產生,當咱們某個數字在填入某個小九宮格時,發現其可填空着的方格在橫行、豎行上都已有該數字,那麼這時咱們沒法在此小九宮格填入該數字了,這時咱們要回溯到上一個小九宮格中,撤銷這個小九宮格填入的該數字,從新選取可填位置填入該數字(這裏不用選取數字,數字已選定)。填入完成後,再回到本次須要填入該數字的小九宮格中選填該數字。咱們須要把1-9這九個數字中的每個數字在九個小九宮格中按照數獨規則都填入一遍。當第9個小九宮格中數字「9」填入完成,數獨徹底解也就生成了。

【算法研究】數獨高效徹底解生成算法的研究和實現

該算法採用分治的思想將整個大九宮格分爲九個小九宮格,1-9九個數字按順序填入,排除了數字之間的限制約束,每一個數字獨立填入的回溯空間大大縮小,某些數字甚至無需回溯,例如此過程當中的數字「1」和「9」就不須要進行回溯。同時咱們產生時結合隨機數選填位置,這樣能保在持數字之間很好的隨機性的同時,又在產生時間上極大的縮短了耗時。這樣思路實現的代碼產生出來的數獨徹底解,計算機耗時基本保持在幾毫秒左右。就是以人工方式手動填入的方法,也可在幾分鐘以內產生一組合法的數獨徹底解。此算法相較於傳統的回溯算法,其效率明顯的提升了不少。

爲了便於區分咱們將1-9這九個數字標識不一樣的顏色。填入完成後的解,以下圖所示。最後經過咱們實現該算法的java代碼的實際測試,其產生10000組解的實際平均耗時爲3.25秒左右。實際測試中咱們使用的是筆記本,後臺也有運行其餘的軟件,咱們有嘗試將測試數據調至10000000組,該次測試過程當中CPU佔用率平均在50%左右,筆記本有輕微發熱,最後耗時爲52.98分鐘,固然這些測試中咱們並無去驗證產生數獨徹底解的惟一性,作這些測試只是爲了驗證數獨徹底解的產生速度。

【算法研究】數獨高效徹底解生成算法的研究和實現

 轉自:http://blog.sina.com.cn/s/blog_a28e3dd90101e1i2.html

相關文章
相關標籤/搜索