舞蹈鏈(Dancing Links)演算法求解數獨

2021-09-06 20:05:07 字數 3398 閱讀 4727

利用舞蹈鏈(dancing links)演算法求解數獨問題,實際上就是下面乙個流程

1、把數獨問題轉換為精確覆蓋問題

2、設計出資料矩陣

3、用舞蹈鏈(dancing links)演算法求解該精確覆蓋問題

4、把該精確覆蓋問題的解轉換為數獨的解

首先看看數獨問題(9*9的方格)的規則

1、每個格仔只能填乙個數字

2、每行每個數字只能填一遍

3、每列每個數字只能填一遍

4、每宮每個數字只能填一遍(宮的概念,參看「演算法實踐——數獨的基本解法」)

那現在就是利用這個規則把數獨問題轉換為精確覆蓋問題

可是,直觀上面的規則,發現比較難以轉換為精確覆蓋問題。因此,把上面的表述換個說法

1、每個格仔只能填乙個數字

2、每行1-9的這9個數字都得填一遍(也就意味著每個數字只能填一遍)

3、每列1-9的這9個數字都得填一遍

4、每宮1-9的這9個數字都得填一遍

這樣理解的話,數獨問題轉換為精確覆蓋問題就相對簡單多了。關鍵就是如何構造精確覆蓋問題中的矩陣

我們把矩陣的每個列都定義成乙個約束條件。

第1列定義成:(1,1)填了乙個數字

第2列定義成:(1,2)填了乙個數字

第9列定義成:(1,9)填了乙個數字

第10列定義成:(2,1)填了乙個數字

第18列定義成:(2,9)填了乙個數字

第81列定義成:(9,9)填了乙個數字

至此,用第1-81列完成了約束條件1:每個格仔只能填乙個數字

第n列(1≤n≤81)定義成:(x,y)填了乙個數字。

n、x、y之間的關係是:x=int((n-1)/9)+1;y=((n-1) mod 9)+1;n=(x-1)×9+y

第82列定義成:在第1行填了數字1

第83列定義成:在第1行填了數字2

第90列定義成:在第1行填了數字9

第91列定義成:在第2行填了數字1

第99列定義成:在第2行填了數字9

第162列定義成:在第9行填了數字9

至此,用第82-162列(共81列)完成了約束條件2:每行1-9的這9個數字都得填一遍

第n列(82≤n≤162)定義成:在第x行填了數字y。

n、x、y之間的關係是:x=int((n-81-1)/9)+1;y=((n-81-1) mod 9)+1;n=(x-1)×9+y+81

第163列定義成:在第1列填了數字1

第164列定義成:在第1列填了數字2

第171列定義成:在第1列填了數字9

第172列定義成:在第2列填了數字1

第180列定義成:在第2列填了數字9

第243列定義成:在第9列填了數字9

至此,用第163-243列(共81列)完成了約束條件3:每列1-9的這9個數字都得填一遍

第n列(163≤n≤243)定義成:在第x列填了數字y。

n、x、y之間的關係是:x=int((n-162-1)/9)+1;y=((n-162-1) mod 9)+1;n=(x-1)×9+y+162

第244列定義成:在第1宮填了數字1

第245列定義成:在第1宮填了數字2

第252列定義成:在第1宮填了數字9

第253列定義成:在第2宮填了數字1

第261列定義成:在第2宮填了數字9

第324列定義成:在第9宮填了數字9

至此,用第244-324列(共81列)完成了約束條件4:每宮1-9的這9個數字都得填一遍

第n列(244≤n≤324)定義成:在第x宮填了數字y。

n、x、y之間的關係是:x=int((n-243-1)/9)+1;y=((n-243-1) mod 9)+1;n=(x-1)×9+y+243

至此,用了324列完成了數獨的四個約束條件,矩陣的列定義完成

那接下來,就是把數獨轉換為矩陣

數獨問題中,每個格仔分兩種情況。有數字的格仔、沒數字的格仔。

有數字的格仔

以例子來說明,在(4,2)中填的是7

把(4,2)中填的是7,解釋成4個約束條件

1、在(4,2)中填了乙個數字。

2、在第4行填了數字7

3、在第2列填了數字7

4、在第4宮填了數字7(座標(x,y)到宮n的公式為:n=int((x-1)/3)×3+int((y-1)/3)+1)

那麼這4個條件,分別轉換成矩陣對應的列為

1、在(4,2)中填了乙個數字。對應的列n=(4-1)×9+2=29

2、在第4行填了數字7。對應的列n=(4-1)×9+7+81=115

3、在第2列填了數字7。對應的列n=(2-1)×9+7+162=178

4、在第4宮填了數字7。對應的列n=(4-1)×9+7+243=277

於是,(4,2)中填的是7,轉成矩陣的一行就是,第29、115、178、277列是1,其餘列是0。把這1行插入到矩陣中去。

沒數字的格仔

還是舉例說明,在(5,8)中沒有數字

把(5,8)中沒有數字轉換成

(5,8)中填的是1,轉成矩陣的一行就是,第44、118、226、289列是1,其餘列是0。

(5,8)中填的是2,轉成矩陣的一行就是,第44、119、227、290列是1,其餘列是0。

(5,8)中填的是3,轉成矩陣的一行就是,第44、120、228、291列是1,其餘列是0。

(5,8)中填的是4,轉成矩陣的一行就是,第44、121、229、292列是1,其餘列是0。

(5,8)中填的是5,轉成矩陣的一行就是,第44、122、230、293列是1,其餘列是0。

(5,8)中填的是6,轉成矩陣的一行就是,第44、123、231、294列是1,其餘列是0。

(5,8)中填的是7,轉成矩陣的一行就是,第44、124、232、295列是1,其餘列是0。

(5,8)中填的是8,轉成矩陣的一行就是,第44、125、233、296列是1,其餘列是0。

(5,8)中填的是9,轉成矩陣的一行就是,第44、126、234、297列是1,其餘列是0。

把這9行插入到矩陣中。由於這9行的第44列都是1(不會有其他行的44列會是1),也就是說這9行中必只有1行(有且只有1行)選中(精確覆蓋問題的定義,每列只能有1個1),是最後解的一部分。這就保證了最後解在(5,8)中只有1個數字。

這樣,從數獨的格仔依次轉換成行(1行或者9行)插入到矩陣中。完成了數獨問題到精確覆蓋問題的轉換。

接下來求解精確覆蓋問題就交給舞蹈鏈(dancing links)演算法,詳情參看

用舞蹈鏈實現數獨2

輸入12 12 12顯示答案,如果沒有顯示就是沒有結果 輸入13 13 13更換數獨開局 輸入0 8 0 8 0 9在指定位置放值 輸入11 11 11檢驗數獨是否正確 include include include rand函式 include srand函式 include consolecol...

HDU 4979(舞蹈鏈 打表)

題意 在0 2 n 1中,選出盡量少的二進位制位有m個1的數,要求包含全部二進位制位含有r個1的數。n 8。解法 就是乙個重複覆蓋,但是不管怎麼剪枝都會超時,所以要打表交上去。這是打表的程式 include include include include include include includ...

舞蹈鏈應用之精確覆蓋模板

這幾天終於鼓起勇氣學了舞蹈鏈這種資料結構,在聯絡的過程中發現一般分為兩種情況 精確覆蓋和重複覆蓋 首先將一下精確覆蓋,顧名思義就是覆蓋全部的元素且只能覆蓋一次 在 實現的方面講即給出的0 1矩陣中找到對應的行號使這些行組成組成的新矩陣每列只有乙個1 模板 include include includ...