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("\n");
 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 }
vijos 1345

 

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("\n");
 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 }
wikioi 2924

 

Posted on 2014-07-29 11:11  cjhahaha  阅读(239)  评论(0编辑  收藏  举报