1 参考链接
http://www.cnblogs.com/steady/archive/2011/03/15/1984791.html#undefined
http://en.wikipedia.org/wiki/Dancing_Links
2 双向链表
可用数组实现
删除x操作
Function Remove
x.left.right <-x.right
x.right.left <- x.left
恢复x
Function Resume
x.left.right <- x
x.right.left <- x
3 精确覆盖(Exact Cover Problem)
给定一个01矩阵, 现在要选择一些行,使得每一列有且仅有一个1
解决办法:搜索
4 数独转化
数独满足的条件:
1. 每个格子都填有数字
2. 每一行都要有1~9这9个数字填入
3. 每一列都要有1~9这9个数字填入
4. 每一坨都要有1~9这9个数字填入
可构造一个729*324的由01构成的矩阵
//i,j,k表示在棋盘上i行j列填入数字k
行:
1到81,表示棋盘中9*9=81个格子是否填入了数字。如果是,则选取的01行在该01列上有1
对应的01列编号为:(i-1)*9+j
81+1到81*2,表示棋盘中9行,每行的9个不同的数字是否填入。棋盘上某行已经填入了某个数字,则在选取的01行上,对应的01列有1。
对应的01列编号为:81+(i-1)*9+k。
81*2+1到81*3,表示棋盘中9列,每列的9个不同的数字是否填入。
对应的01列编号为:81*2+(j-1)*9+k。
81*3+1到81*4,表示棋盘中9块,每块的9个不同的数字是否填入。
01行是状态。数独做完后的状态是什么,就是棋盘上每个格子填入的究竟是什么数字
所以,01行表示的是,棋盘上某个格子填入的是什么数字。
那01行的行数就是9*9*9。
5 Sample
vijos 1345 数独大赛
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXA = 10; 5 const int MAXC = 324+10; 6 const int MAXR = 729+10; 7 const int MAXN = MAXR*4+MAXC; 8 9 int n = 324, T; 10 11 struct DancingLinks{ 12 char c; 13 int sz, S[MAXC], 14 Col[MAXN], Row[MAXN], 15 L[MAXN], R[MAXN], U[MAXN], D[MAXN], 16 head[MAXA][MAXA][MAXA], 17 anna[MAXA][MAXA]; 18 19 inline void Clear(){ 20 memset(S, 0, sizeof(S)); 21 memset(Col, 0, sizeof(Col)); 22 for (int i=0; i<=81*4; i++) 23 L[i] = i-1, R[i] = i+1, 24 U[i] = i, D[i] = i; 25 L[0] = n, R[n] = 0; 26 sz = n; 27 } 28 29 inline void Scan(){ 30 do 31 c = getchar(); 32 while (!(48<=c && c<=57)); 33 34 for (int i=1; i<=9; i++) 35 for (int j=1; j<=9; j++) 36 anna[i][j] = c-48, 37 c = getchar(); 38 } 39 40 inline void Print(){ 41 for (int i=1; i<=9; i++) 42 for (int j=1; j<=9; j++) 43 printf("%d", anna[i][j]); 44 printf(" "); 45 } 46 47 inline int _GetPortion(int i,int j){ 48 return (--i/3)*3+(--j/3+1); 49 } 50 51 inline void AddNode(int c,int sz){ 52 U[D[c]] = sz, D[sz] = D[c]; 53 U[sz] = c, D[c] = sz; 54 S[c] ++, Col[sz] = c; 55 } 56 57 inline void Remove(int c){ 58 L[R[c]] = L[c], R[L[c]] = R[c]; 59 for (int i=D[c]; i!=c; i=D[i]) 60 for (int j=R[i]; j!=i; j=R[j]) 61 U[D[j]]=U[j], D[U[j]]=D[j], 62 -- S[Col[j]]; 63 } 64 65 inline void Resume(int c){ 66 for (int i=U[c]; i!=c; i=U[i]) 67 for (int j=L[i]; j!=i; j=L[j]) 68 U[D[j]] = j, D[U[j]] = j, 69 ++ S[Col[j]]; 70 L[R[c]] = c, R[L[c]] = c; 71 } 72 73 inline bool DFS(int k){ 74 if (k>81) return true; 75 76 int c = R[0], temp; 77 for (int i=R[0]; i!=0; i=R[i]){ 78 if (!S[i]) return false; 79 if (S[i]<S[c]) c = i; 80 } 81 Remove(c); 82 83 for (int i=D[c]; i!=c; i=D[i]){ 84 temp = Row[i]; 85 anna[temp/100][(temp/10)%10] = temp%10; 86 for (int j=R[i]; j!=i; j=R[j]) 87 Remove(Col[j]); 88 89 if (DFS(k+1)) return true; 90 91 for (int j=L[i]; j!=i; j=L[j]) 92 Resume(Col[j]); 93 } 94 Resume(c); 95 96 return false; 97 } 98 99 inline void AddRow(int i, int j, int k){ 100 for (int u=1; u<=4; u++) 101 L[sz+u] = sz+u-1, R[sz+u] = sz+u+1, 102 Row[sz+u] = 100*i+10*j+k; 103 104 L[sz+1] = sz+4, R[sz+4] = sz+1; 105 head[i][j][k] = sz+1; 106 AddNode(81*0+(i-1)*9+j, ++sz); 107 AddNode(81*1+(i-1)*9+k, ++sz); 108 AddNode(81*2+(j-1)*9+k, ++sz); 109 AddNode(81*3+(_GetPortion(i,j)-1)*9+k, ++sz); 110 } 111 112 inline void EatCarrot(){ 113 Clear(); 114 Scan(); 115 116 for (int i=1; i<=9; i++) 117 for (int j=1; j<=9; j++) 118 if (anna[i][j]) AddRow(i, j, anna[i][j]); 119 else 120 for (int k=1;k<=9;k++) 121 AddRow(i, j, k); 122 123 int k = 0; 124 for (int i=1; i<=9; i++) 125 for (int j=1; j<=9; j++) 126 if (anna[i][j]){ 127 ++ k; 128 Remove(Col[head[i][j][anna[i][j]]]); 129 for (int u=R[head[i][j][anna[i][j]]]; u!=head[i][j][anna[i][j]]; u=R[u]) 130 Remove(Col[u]); 131 } 132 133 DFS(k+1); 134 Print(); 135 } 136 }Rabbit; 137 138 int main(){ 139 scanf("%d", &T); 140 while (T--) 141 Rabbit.EatCarrot(); 142 }
wikioi 2924数独挑战
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXA = 10; 5 const int MAXC = 324+10; 6 const int MAXR = 729+10; 7 const int MAXN = MAXR*4+MAXC; 8 9 int n = 324, T; 10 11 struct DancingLinks{ 12 int sz, S[MAXC], 13 Col[MAXN], Row[MAXN], 14 L[MAXN], R[MAXN], U[MAXN], D[MAXN], 15 head[MAXA][MAXA][MAXA], 16 anna[MAXA][MAXA]; 17 18 inline void Clear(){ 19 memset(S, 0, sizeof(S)); 20 memset(Col, 0, sizeof(Col)); 21 for (int i=0; i<=81*4; i++) 22 L[i] = i-1, R[i] = i+1, 23 U[i] = i, D[i] = i; 24 L[0] = n, R[n] = 0; 25 sz = n; 26 } 27 28 inline void Scan(){ 29 for (int i=1; i<=9; i++) 30 for (int j=1; j<=9; j++) 31 scanf("%d", &anna[i][j]); 32 } 33 34 inline void Print(){ 35 for (int i=1; i<=9; i++){ 36 for (int j=1; j<=9; j++) 37 printf("%d ", anna[i][j]); 38 printf(" "); 39 } 40 } 41 42 inline int _GetPortion(int i,int j){ 43 return (--i/3)*3+(--j/3+1); 44 } 45 46 inline void AddNode(int c,int sz){ 47 U[D[c]] = sz, D[sz] = D[c]; 48 U[sz] = c, D[c] = sz; 49 S[c] ++, Col[sz] = c; 50 } 51 52 inline void Remove(int c){ 53 L[R[c]] = L[c], R[L[c]] = R[c]; 54 for (int i=D[c]; i!=c; i=D[i]) 55 for (int j=R[i]; j!=i; j=R[j]) 56 U[D[j]]=U[j], D[U[j]]=D[j], 57 -- S[Col[j]]; 58 } 59 60 inline void Resume(int c){ 61 for (int i=U[c]; i!=c; i=U[i]) 62 for (int j=L[i]; j!=i; j=L[j]) 63 U[D[j]] = j, D[U[j]] = j, 64 ++ S[Col[j]]; 65 L[R[c]] = c, R[L[c]] = c; 66 } 67 68 inline bool DFS(int k){ 69 if (k>81) return true; 70 71 int c = R[0], temp; 72 for (int i=R[0]; i!=0; i=R[i]){ 73 if (!S[i]) return false; 74 if (S[i]<S[c]) c = i; 75 } 76 Remove(c); 77 78 for (int i=D[c]; i!=c; i=D[i]){ 79 temp = Row[i]; 80 anna[temp/100][(temp/10)%10] = temp%10; 81 for (int j=R[i]; j!=i; j=R[j]) 82 Remove(Col[j]); 83 84 if (DFS(k+1)) return true; 85 86 for (int j=L[i]; j!=i; j=L[j]) 87 Resume(Col[j]); 88 } 89 Resume(c); 90 91 return false; 92 } 93 94 inline void AddRow(int i, int j, int k){ 95 for (int u=1; u<=4; u++) 96 L[sz+u] = sz+u-1, R[sz+u] = sz+u+1, 97 Row[sz+u] = 100*i+10*j+k; 98 99 L[sz+1] = sz+4, R[sz+4] = sz+1; 100 head[i][j][k] = sz+1; 101 AddNode(81*0+(i-1)*9+j, ++sz); 102 AddNode(81*1+(i-1)*9+k, ++sz); 103 AddNode(81*2+(j-1)*9+k, ++sz); 104 AddNode(81*3+(_GetPortion(i,j)-1)*9+k, ++sz); 105 } 106 107 inline void EatCarrot(){ 108 Clear(); 109 Scan(); 110 111 for (int i=1; i<=9; i++) 112 for (int j=1; j<=9; j++) 113 if (anna[i][j]) AddRow(i, j, anna[i][j]); 114 else 115 for (int k=1;k<=9;k++) 116 AddRow(i, j, k); 117 118 int k = 0; 119 for (int i=1; i<=9; i++) 120 for (int j=1; j<=9; j++) 121 if (anna[i][j]){ 122 ++ k; 123 Remove(Col[head[i][j][anna[i][j]]]); 124 for (int u=R[head[i][j][anna[i][j]]]; u!=head[i][j][anna[i][j]]; u=R[u]) 125 Remove(Col[u]); 126 } 127 128 DFS(k+1); 129 Print(); 130 } 131 }Rabbit; 132 133 int main(){ 134 Rabbit.EatCarrot(); 135 }