
使用 Dancing Links (DLX) 解決精確覆蓋問題

此文章尚未完成
這學期的 ADA 第一週作業就出了這題,甚至還沒開始上演算法,非常可怕。雖然助教說爆搜剪枝瘋狂優化會過,但我還是覺得寫 DLX 比較好玩,所以就順便紀錄一下。
精確覆蓋問題
定義
引用維基百科的說明:
維基百科 - Exact cover
在一個全集
精確覆蓋問題(Exact cover)指找出一組解或證明其不存在,是一個 NP-完全問題。
範例
樸素做法
直接枚舉
Knuth’s Algorithm X
💡Hint:文章的行指的是橫排(row),列指的是縱排(column)。
核心概念
X 演算法的核心概念其實非常簡單:在枚舉答案時,假設我選取了
演算法內容
我們將剛剛的範例搬下來再用一次,首先將資料離散化得到一個關聯矩陣
注意此時每一行代表一種選擇,列代表這種選擇覆蓋的區域。X 演算法的步驟如下:
- 如果目前矩陣
是空的,代表目前局部解是一個合法的解,直接回傳,演算法停止。 - 如果有某一列沒有 1 則失敗,回朔到上一層。有的話則選擇 1 數量最少的列
。 - 選擇其中一行
使得 。 - 將第
列加入目前局部解。 - 對於所有
使得 ,刪除所有使 的行 ,再刪除第 列。 - 對新得到的小矩陣
遞迴執行演算法。
OI Wiki 給出了詳細的步驟說明跟範例,這裡就不贅述了。
優化
X 演算法需要不斷地刪除、恢復(回朔時)矩陣的行列,並且矩陣中的 1 其實是很稀疏的,直接開二維陣列的話空間複雜度也會炸掉。
使用 Dancing Links 優化 Algorithm X
實現
1 |
|
範例輸入 1
1 | 6 7 |
範例輸出 1
1 | YES |
範例輸入 2
1 | 6 7 |
範例輸出 2
1 | NO |
實際應用
其實前面的內容都不算難,此類問題最大的難點在於要如何把原始問題轉化為精確覆蓋問題,從而使用 DLX 解決,所以以下我們就來看看幾個範例吧。
A-Puzzle-A-Day
數獨
- 標題: 使用 Dancing Links (DLX) 解決精確覆蓋問題
- 作者: HyperSoWeak
- 撰寫于 : 2024-09-13 09:20:51
- 更新于 : 2024-09-20 05:12:44
- 連結: https://hypersoweak.github.io/blog/dancing-links/
- 版權宣告: 本作品采用 CC BY-NC-SA 4.0 进行许可。