Dancing Links 精確覆蓋模板
#include<iostream><br />#include<stdio.h><br />#include<string.h><br />#include<vector><br />#include<math.h><br />#define inf 0x3fffffff<br />using namespace std;<br />const int N = 305; /*列數*/<br />const int M = 4000; /*點數*/<br />int map[N][N]; /* 01矩陣表 */<br />int U[M], D[M], R[M], L[M], rs[N];<br />int size[N], head, row[M], col[M];<br />int n, m, k;<br />int ans[N], ansL;<br />bool yes;<br />int nodecnt;<br />void read() {<br /> /* 讀入初始化 */<br />}<br />void init(int m) {<br /> /* 初始化,m 為列數 */<br /> memset(size, 0, sizeof (size));<br /> memset(col, -1, sizeof (col));<br /> nodecnt = m + 1;<br /> for (int i = 0; i <= m; i++) {<br /> L[i] = (i - 1);<br /> R[i] = (i + 1);<br /> col[i] = i;<br /> D[i] = U[i] = i;<br /> }<br /> L[0] = m;<br /> R[m] = 0;<br /> size[0] = INT_MAX;<br />}<br />inline void remove(int id) {<br /> int i, j;<br /> R[ L[id] ] = R[id];<br /> L[ R[id] ] = L[id];<br /> for (i = D[id]; i != id; i = D[i])<br /> for (j = R[i]; j != i; j = R[j]) {<br /> U[ D[j] ] = U[j];<br /> D[ U[j] ] = D[j];<br /> size[ col[j] ]--;<br /> }<br />}<br />inline void resume(int id) {<br /> int i, j;<br /> for (i = U[id]; i != id; i = U[i])<br /> for (j = L[i]; j != i; j = L[j]) {<br /> size[ col[j] ]++;<br /> U[ D[j] ] = j;<br /> D[ U[j] ] = j;<br /> }<br /> R[ L[id] ] = id;<br /> L[ R[id] ] = id;<br />}<br />int check() {<br /> /* 此函數使用幾率不大 */<br /> /* 檢查解的合法性,所選擇的列存在ans數組中 */<br />}<br />void dfs(int num) {<br /> if (num >= ansL) return; /* 輸出選擇最少行的解的方案,須注釋掉下面那句 */<br /> if (R[0] == 0) {<br /> ansL = num; /* ansL 為該組解所選行的個數,亦即 ans 數組裡面的個數 */<br /> yes = check(); /* 可能有多組可行解,檢查解的合法性 */<br /> return;<br /> }<br /> int i, j, id = 0, min = inf;<br /> for (i = R[0]; i != 0; i = R[i])<br /> if (size[i] < min) {<br /> min = size[i];<br /> id = i;<br /> }<br /> remove(id);<br /> for (i = D[id]; i != id; i = D[i]) {<br /> ans[num] = row[i];<br /> for (j = R[i]; j != i; j = R[j])<br /> remove(col[j]);<br /> dfs(num + 1);<br /> if (yes) return; /* 如果要求輸出選擇最少行數的解,這一句要注釋掉 */<br /> for (j = L[i]; j != i; j = L[j])<br /> resume(col[j]);<br /> }<br /> resume(id);<br />}<br />inline void insert(int i, int *tt, int c) {<br /> for (int j = 0; j < c; j++, nodecnt++) {<br /> int x = tt[j];<br /> row[nodecnt] = i;<br /> col[nodecnt] = x;<br /> size[x]++;<br /> U[nodecnt] = x;<br /> D[nodecnt] = D[x];<br /> U[D[x]] = nodecnt;<br /> D[x] = nodecnt;<br /> if (j == 0) L[nodecnt] = R[nodecnt] = nodecnt;<br /> else {<br /> L[nodecnt] = nodecnt - 1;<br /> R[nodecnt] = nodecnt - j;<br /> R[nodecnt - 1] = nodecnt;<br /> L[nodecnt - j] = nodecnt;<br /> }<br /> }<br />}<br />void build() {<br /> memset(map, 0, sizeof (map));<br /> {<br /> /* 一些語句 */<br /> /* 建 01 矩陣,這裡可以視情況而定,有些題目可以直接得到 tt 數組 */<br /> }<br /> int tt[N], c = 0;<br /> int t = n * k + 1;<br /> for (int i = 1; i < t; i++) { /* 掃一遍所有的行,檢查每一行的 1 */<br /> c = 0;<br /> for (int j = 1; j < t; j++)<br /> if (map[i][j] == 1) tt[c++] = j;<br /> insert(i, tt, c); /*插入,tt 數組裡面是 01 矩陣裡每一行裡面1所在的列,c 為 1 的個數*/<br /> }<br />}<br />void solve() {<br /> ansL = inf;<br /> yes = false;<br /> dfs(0);<br /> if (yes) {<br /> /*處理答案,所選擇的行存在 ans 數組中*/<br /> } else {<br /> /* 輸出無解資訊 */<br /> puts("No solution");<br /> }<br /> return;<br />}<br />int main() {<br /> while (scanf("%d%d%d", &n, &m, &k) != EOF) {<br /> read(); /* 讀入初始化 */<br /> init(n * k); /* 初始化,n*k 為列數 */<br /> build(); /* 建圖 */<br /> solve(); /* 問題求解 */<br /> }<br /> return 0;<br />}