解決這類問題的大體思路:
1)判斷所有的情況數,作為列
2)判斷所有的條件數,作為行
3)判斷每一行滿足哪些條件,可以插入1
4)判斷是精確覆蓋還是重複覆蓋
5)注意輸入輸出
精確覆蓋
struct dlx
///第0個結點(表頭head)左指標指向node1,右指標指向nodem
///第m個結點右指標指向head,使得行首結點首尾相接
l[0]
=m,r[0]
=1; r[m]=0
; siz=m;
clclow
(h);
///列首結點初始化為-1,表明該行全為0,沒有指向哪個為1的結點
clc(ans)
; ansed=0;
///答案的數量為0
}void
link
(int r,
int c)
else
return;}
void
del(
int c)
///刪除列及對應的行
return;}
void
recover
(int c)
///恢復列及對應的行
r[l[c]
]=c;
///恢復列首結點
l[r[c]
]=c;
return;}
bool
dancing
(int dep)
///開始跳舞
int c=r[0]
;///表頭右指標指向的列首結點c
del(c)
;///刪除第c列,及該列的1所在的行
for(
int i=d[c]
;i!=c;i=d[i]
)return
false;}
}dlx;
模板題:
exact cover(hust 1017)
重複覆蓋:
其實是準確覆蓋的轉化模型。**與精確覆蓋的區別:首先選擇當前要覆蓋的列,將該列刪除,列舉覆蓋到該列的所有行:對於某一行r,假設認為它是解集中的乙個,那麼該行所能覆蓋到的列都不必再搜,所以刪除該行覆蓋到的所有列。注意此時不用刪去覆蓋到這些列的其它行,因為一列中允許有多個1。
h()函式剪枝利用的思想是a*搜尋中的估價函式。即,對於當前的遞迴深度k下的矩陣,估計其最好情況下(即最少還需要多少步)才能出解。也就是,如果將能夠覆蓋當前列的所有行全部選中,去掉這些行能夠覆蓋到的列,將這個操作作為一層深度。重複此操作直到所有列全部出解的深度是多少。如果當前深度加上這個估價函式返回值,其和已然不能更優(也就是已經超過當前最優解),則直接返回,不必再搜。
1)刪除/恢復函式不同:精確覆蓋是刪除/恢復行及對應的列,重複覆蓋是刪除/恢復列
2)精確覆蓋由於是np問題,所以使用a*優化
3)dancing函式有區別,見**
#include
#include
#include
#define clc(x) memset(x,0,sizeof(x))
#define clclow(x) memset(x,-1,sizeof(x))
using
namespace std;
const
int maxn=15*
15+5,maxnode=maxn*maxn,inf=
1000000000
;struct dlx
///第0個結點(表頭head)左指標指向node1,右指標指向nodem
///第m個結點右指標指向head,使得行首結點首尾相接
l[0]
=m,r[0]
=1; r[m]=0
; siz=m;
clclow
(h);
///列首結點初始化為-1,表明該行全為0,沒有指向哪個為1的結點
clc(ans)
; ansed=inf;
///次數初始化為inf
}void
link
(int r,
int c)
else
return;}
void
remove
(int c)
///刪除第i列
return;}
void
resume
(int c)
///恢復列
return;}
inth()
///ida*的h函式,獲得代價
return ans;
}void
dancing
(int dep)
///開始跳舞
int c=r[0]
;///表頭右指標指向的列首結點c
for(
int i=r[0]
;i!=
0;i=r[i])if
(s[i]
) c=i;
//del(c);///精確覆蓋
for(
int i=d[c]
;i!=c;i=d[i]
)//recover(c);///精確覆蓋
return;}
}dlx;
DLX演算法合集 I
dlx是一種相當神奇的資料結構,通常用於解決矩陣 多為稀疏矩陣 的 重複 精確 覆蓋的問題。不過一般這類問題的難點是抽出轉化關係,剩下的幾乎就是套模板 include include include include include include includeusing namespace std...
P4929 模板 舞蹈鏈 DLX
n m 的矩形有 0 1 要求選出若干行使得每一列有且僅有乙個 1 精確覆蓋問題指的是乙個集合 s 和它的若干個子集集合 t 要求選出 t 的乙個子集使得裡面的集合元素剛好覆蓋集合 s dlx 全稱是 dancing link x 其中 dancing link 是指交叉十字迴圈雙向鏈,x 是指暴搜...
IDEA 方法注釋模板和類注釋模板
1.類注釋模板 在編輯區域輸入你想要注釋的內容,點選應用,再點選儲存,在你建立新的類時就可以自動生成了 2.方法注釋模板 開啟 file setting editor livetemplates 點選右邊上面那個綠色的 號,選擇template group雙擊,然後彈出乙個視窗,起名,然後點選ok ...