DANCING LINKS解決重複覆蓋問題

2021-07-25 02:31:51 字數 1951 閱讀 3386

問題描述:

給定乙個n*m的矩陣,有些位置為1,有些位置為0。如果g[i][j]==1則說明i行可以覆蓋j列。

problem:

1)選定最少的行,使得每列有且僅有乙個1.

2)選定最少的行,使得每列至少乙個1.

dlx原理:

這類屬於np問題的問題,可以使用搜尋解決。但是普通的搜尋必超時無疑。因此我們要設法加優化來加快速度。

dancing links從資料結構方面對此類搜尋進行了優化,通過僅保留矩陣中有用的部分提高了搜尋速度。dlx的儲存結構採用迴圈十字鍊錶,在搜尋過程中不斷將不需要的部分切除,隨著迭代深度的增加,矩陣迅速變得稀疏。

甚至一些你想不到的優化,dlx都替你想好了。

對於problem1)的解:

轉化模型:dlx精確覆蓋。

dlx 精確覆蓋對於當前矩陣的處理是,首先將當前要覆蓋的列以及使得能夠覆蓋到該列的行全部去掉,然後再逐行列舉新增的方法。這是由其「有且僅有乙個1」的條件 決定的。列舉某一行r,則設定當前列的解為該行r,那麼該行能夠覆蓋到的列必然全部都可以不必再搜,因此將該行r覆蓋到的列全部去掉。又由於去掉的那些列 都相當於已經有了解,那麼能夠覆蓋到那些去掉的列的行也應當全部去掉。

搜完之後記得resume。

對於problem2)的解:

轉換模型:dlx重複覆蓋。

dlx 重複覆蓋對於當前矩陣的處理是,將當前列去掉,並將選作當前列的解的行能夠覆蓋到的列全部去掉。因為不需要每列僅由乙個1去覆蓋,因此不必要把能夠覆蓋某 一列的所有行全部去掉。因此remove和resume函式的寫法將會有所不同(獸家在這裡糾結了一會兒= =)。這是與problem1)的第乙個區別。

第二個區別是,由於矩陣密度下降會變慢(因為去掉的少了),因此要加上乙個強剪枝。這個 剪枝利用的思想是a*搜尋中的估價函式。即,對於當前的遞迴深度k下的矩陣,估計其最好情況下(即最少還需要多少步)才能出解。也就是,如果將能夠覆蓋當 前列的所有行全部選中,去掉這些行能夠覆蓋到的列,將這個操作作為一層深度。重複此操作直到所有列全部出解的深度是多少。如果當前深度加上這個估價函式返 回值,其和已然不能更優(也就是已經超過當前最優解),則直接返回,不必再搜。(其實平時的搜尋也會不自覺地使用這個剪枝思想吧)。

關於迴圈十字鍊錶的構造:

採 用靜態鍊錶,不過也不需要記憶體池。使用l,r,d,u四個陣列記錄某節點上下左右鄰居為誰。使用s記錄某列有多少個節點。更新思想同煉表。remove之 後會產生一些孤立節點。這看上去不怎麼好。但是我們就是要利用這些孤立節點來完成優化。比如刪掉節點i,則l[r[i]] = l[i],r[l[i]] = r[i]。這樣i這個節點被孤立掉。但是後面resume的時候使用如下語句:l[r[i]] = i,r[l[i]] = i。巧妙地「變廢為寶」。

優化:對於深度k下當前列的選擇,採用選擇1的個數最少的決策。這是顯然的。hdu2295的試驗表明,隨便選一列將近800ms,而採用這個策略將達到500ms。不過對於當前列的選擇,還是要根據具體情況確定。有時候你的**比別人慢,很可能就是因為這個列的選擇。

推薦題目:

problem1) :

hust1017 **dlx精確覆蓋。

problem2):

hdu2295 二分+dlx重複覆蓋。

dancing links**中講到的一題,並以此為基礎使另外一些型別的題目轉化為此種精確區間覆蓋模型用dlx解決。

法描述如下:

深搜:1、如果矩陣為空,得到結果,返回

2、從矩陣中選擇一列,以選取最少元素的列為優化方式

3、刪除該列及其覆蓋的行

4、對該列的每一行元素:

刪除一行及其覆蓋的列,

5、進行下一層搜尋,如果成功則返回

6、恢復現場,跳至4

7、恢復所選擇行

用雙向十字鍊錶來維護該矩陣,方便刪除與恢復,其中刪除操作:

r[l[i]]=l[i];

l[r[i]]=r[i];

恢復操作:

r[l[i]]=i;

l[r[i]]=i;

dancing links解決X問題的C 實現

x問題,也稱精確覆蓋問題,就是給定乙個01矩陣,需要從中選取一些行組成乙個子矩陣,這個子矩陣的每一列有且僅有乙個1。這個問題聽起來就知道很難,必須使用回溯演算法來解決,但是我們知道回溯演算法要提高效率,就必須做好剪枝和回溯恢復的工作。這時演算法大師donald e.knoth給出了乙個巧妙的資料結構...

Dancing links 資料結構

前言 想必很多人學習這個演算法,都是因為數獨的原因,雖然這個演算法並不是專門解決數獨的,但是,在解決數獨方面,仍然比暴力搜尋有很大,優勢,在解法方面就顯得很方便,複雜度方面也很客觀,總得來說這個演算法的思想並不是很難理解,但是沒有一種很好的資料結構能很好的實現該演算法,由此dlx這種資料結構就誕生了...

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

利用舞蹈鏈 dancing links 演算法求解數獨問題,實際上就是下面乙個流程 1 把數獨問題轉換為精確覆蓋問題 2 設計出資料矩陣 3 用舞蹈鏈 dancing links 演算法求解該精確覆蓋問題 4 把該精確覆蓋問題的解轉換為數獨的解 首先看看數獨問題 9 9的方格 的規則 1 每個格仔只...