Sudoku MongoDB links Template

Source: Internet
Author: User

Recommended papers: momodi's Dancing Links application in search, Knuth's DLX paper, and Chen danqi's Dancing Links Application

 

Dancing Links is used to optimize the DFS process for a class of precise coverage issues.

The exact coverage problem is that in a 01 matrix, some columns that exercise each column have only one.

The solution is the X algorithm proposed by Knuth:

1. All matrices are deleted, and the search is successfully exited.

2. select a column c with the least elements (you can select a column as needed) to delete the column. enumerate the rows with 1 in the column r as part of the solution and delete all columns with 1 in the row r.

3. recursive call. If the call succeeds, return the result. If the call fails, return the result.

 

In general, the bool array is used in the search to identify whether rows and columns are deleted. Finding all rows with 1 in the column requires r times, and searching all columns in the row requires c times,

However, during the search process, the rows and columns of the matrix are constantly deleted and reduced. The rows and columns that contain the first column are few and become sparse matrices,

In this case, using r or c queries is a waste of time.

Dancing Links uses a two-way Cyclic Cross-linked list to store the matrix. The size of the linked list decreases continuously during the search process, and r or c is not required for Traversing once.

Two-way linked list deletion:

L [R [x] = L [x]; R [L [x] = R [x];

The restoration of a two-way linked list is also simple:

L [R [x] = x; R [L [x] = x;

Knuth named the linked list that supports this operation Dancing Links.

 

Conversion from Sudoku to exact coverage

DT alone has four constraints:

1. Only one number k can be placed in line I.

2. Only one digit k can be placed in column j.

3. Only one digit K can be placed in block (I, j ).

4. Only one number can be placed in column J of row I.

 

So create a 01 matrix:

The number of rows is N * n, and N * n grids. Each grid may contain N, each of which may correspond to a row.

The number of columns is 4 * n, which represents the four constraints of N * n grids.

If K already exists in the J column of the DT single row, insert four 1 columns in the (I * n + J) * n + k rows, and the columns are:

I * n + k-1

N * n + J * n + k-1

2 * n + block (I, j) * n + k-1

3 * n + I * n + J

Otherwise, insert n rows, k = 1 to n.

If n = 16, there are 4096 rows and 1024 columns, and the matrix traversal needs to be 4096*1024 = 4194304 times,

However, the number of 1 entries is only 4096*4 = 16384, and it takes only 16384 times for the dancing links traversal.

In this comparison, we can see that dancing links saves a lot of time.

You can call the DLX algorithm to find a solution for a sudoku or to judge whether there is no solution.

 

Queen n's problem can also be converted to precise coverage.

There is also a type of repeated coverage problem:

In a 01 matrix, select some exercise columns with at least 1.

Use the * algorithm to solve the problem.

 

 

Sudoku template:

//POJ3076 736 KB 172 ms G++ 2689 B #include<cstdio>#define N 4099#define M 1025int m=4,n=m*m,H=4*n*n,cnt,size[M],ans[16][16];struct Node{    int r,c;    Node *U,*D,*L,*R;}node[16385],row[N],col[M],head,*p;void init(int r,int c){    cnt=0;    head.L=head.R=head.U=head.D=&head;    for(int i=0;i<c;i++){        col[i].r=r;        col[i].c=i;        col[i].L=&head;        col[i].R=head.R;        col[i].U=col[i].D=col[i].L->R=col[i].R->L=&col[i];        size[i]=0;    }    for(int i=r-1;i>=0;i--){        row[i].r=i;        row[i].c=c;        row[i].U=&head;        row[i].D=head.D;        row[i].L=row[i].R=row[i].U->D=row[i].D->U=&row[i];    }}void insert(int r,int c){    p=&node[cnt++];    p->r=r;    p->c=c;    p->R=&row[r];    p->L=row[r].L;    p->L->R=p->R->L=p;    p->U=&col[c];    p->D=col[c].D;    p->U->D=p->D->U=p;    ++size[c];}void delLR(Node *p){    p->L->R=p->R;    p->R->L=p->L;}void delUD(Node *p){    p->U->D=p->D;    p->D->U=p->U;}void resumeLR(Node *p){p->L->R=p->R->L=p;}void resumeUD(Node *p){p->U->D=p->D->U=p;}void cover(int c){    if(c==H)        return;    delLR(&col[c]);    Node *R,*C;    for(C=col[c].D;C!=&col[c];C=C->D)for(R=C->L;R!=C;R=R->L){--size[R->c];delUD(R);}}void resume(int c){    if(c==H)        return;    Node *R,*C;    for(C=col[c].U;C!=&col[c];C=C->U)for(R=C->R;R!=C;R=R->R){++size[R->c];resumeUD(R);}    resumeLR(&col[c]);}int dfs(int k){    if(head.L==&head)return 1;    int INF=-1u>>1,r,c=-1;Node *p,*rc;    for(p=head.R;p!=&head;p=p->R)        if(size[p->c]<INF)            INF=size[c=p->c];if(!size[c])return 0;    cover(c);    for(p=col[c].D;p!=&col[c];p=p->D){        for(rc=p->L;rc!=p;rc=rc->L)            cover(rc->c);r=p->r-1;ans[r/(n*n)][r/n%n]=r%n;        if(dfs(k+1))            return 1;        for(rc=p->R;rc!=p;rc=rc->R)            resume(rc->c);    }    resume(c);    return 0;}void insert(int i,int j,int k){int r=(i*n+j)*n+k;insert(r,i*n+k-1);insert(r,n*n+j*n+k-1);insert(r,2*n*n+(i/m*m+j/m)*n+k-1);insert(r,3*n*n+i*n+j);}char s[16][20];void Sudoku(){int i,j,k;init(n*n*n+1,H);for(i=0;i<n;i++)for(j=0;j<n;j++)if(s[i][j]!='-')insert(i,j,k=s[i][j]-'A'+1);else{for(k=1;k<=n;k++)insert(i,j,k);}dfs(0);for(i=0;i<n;i++){for(j=0;j<n;j++)putchar(ans[i][j]+'A');puts("");}puts("");}int main(){int i;    while(~scanf("%s",s[0])){for(i=1;i<n;i++)scanf("%s",s[i]);Sudoku();}}

Precise coverage:

// 01 The Matrix perfectly covers HUST1017 # include <iostream> # include <cstdio> # include <vector> using namespace std; /***** maximum row ***/# define MAXROW 1005/***** maximum column ***/# define MAXCOL 1005int ans [MAXROW + 5]; struct DancingLinksNode {int r, c;/*** the row and column location of the node ***/DancingLinksNode * U, * D, * L, * R; /*** node pointer **/}; DancingLinksNode node [MAXROW * MAXCOL]; /***** slave node *****/DancingLinksNode row [MAXROW];/***** row header *****/DancingLinksNode col [MAXCOL] ;/***** Column header *****/DancingLinksNode head;/***** header *****/int cnt; /***** how many nodes are used *****/int size [MAXCOL];/***** how many fields are contained in the column *****/int m, n; /***** table row and column variables *****/void init (int r, int c)/***** initialization, r, c Indicates the table size. ***/{cnt = 0;/*** sets the usable node to the first ***/head. r = r;/***** the r and c of the head node indicate the table size for future reference *****/head. c = c; head. L = head. R = head. U = head. D = & head;/***** initialize the head node *****/for (int I = 0; I <c; ++ I) /*** initialize the column header ***/{col [I]. r = r; col [I]. c = I; col [I]. L = & head; col [I]. R = head. r; col [I]. l-> R = col [I]. r-> L = & col [I]; col [I]. U = col [I]. D = & col [I]; size [I] = 0 ;}for (int I = r-1; I>-1; -- I)/*** initialize the line header, if row [I] is encountered during deletion, c = c should be skipped ***/{row [I]. r = I; row [I]. c = c; row [I]. U = & head; row [I]. D = head. d; row [I]. u-> D = row [I]. d-> U = & row [I]; row [I]. L = row [I]. R = & row [I] ;}} inline void addNode (int r, int c)/*** adds a node, which is the r row in the original table, column c *** /{DancingLinksNode * ptr = & node [cnt ++];/***** find an unused node *****/ptr-> r = r; /***** set the row and column numbers of nodes *****/ptr-> c = c; ptr-> R = & row [r]; /***** Add the node to the two-way linked list *****/ptr-> L = row [r]. l; ptr-> L-> R = ptr-> R-> L = ptr; ptr-> U = & col [c]; ptr-> D = col [c]. d; ptr-> U-> D = ptr-> D-> U = ptr; ++ size [c]; /***** Add the size field to 1 *****/} inline void delLR (DancingLinksNode * ptr) /***** Delete the left and right directions of the node pointed to by ptr *****/{ptr-> L-> R = ptr-> R; ptr-> R-> L = ptr-> L;} inlin E void delUD (DancingLinksNode * ptr) /***** Delete the upstream and downstream directions of the node pointed to by ptr *****/{ptr-> U-> D = ptr-> D; ptr-> D-> U = ptr-> U;} inline void resumeLR (DancingLinksNode * ptr) /***** reset the left and right directions of the node pointed to by ptr *****/{ptr-> L-> R = ptr-> R-> L = ptr ;} inline void resumeUD (DancingLinksNode * ptr) /***** reset the upstream and downstream directions of the node pointed to by ptr *****/{ptr-> U-> D = ptr-> D-> U = ptr ;} inline void cover (int c)/***** overwrite section c ***/{if (c = n) /***** c = n indicates the header *****/return; delLR (& col [C]);/***** Delete the header *****/DancingLinksNode * R, * C; for (C = col [c]. D; C! = (& Col [c]); C = C-> D) {if (C-> c = n) continue; for (R = C-> L; R! = C; R = R-> L) {if (R-> c = n) continue; -- size [R-> c]; delUD (R );} delLR (C) ;}} inline void resume (int c)/***** reset column c *****/{if (c = n) return; dancingLinksNode * R, * C; for (C = col [c]. u; C! = (& Col [c]); C = C-> U) {if (C-> c = n) continue; resumeLR (C ); for (R = C-> R; R! = C; R = R-> R) {if (R-> c = n) continue; ++ size [R-> c]; resumeUD (R );}} resumeLR (& col [c]);/***** Add the column header to the header *****/} bool search (int k) /***** search core algorithm, k indicates the number of search layers *****/{if (head. L = (& head)/*** returns true ***/{printf ("% d \ n", k) if the search is successful ); for (int I = 0; I <k; I ++) printf ("% d \ n", ans [I]); return true ;} /*** c indicates the location of the object in the next column, and finds the smallest number of branches to overwrite it. ***/int INF = (1 <30), c =-1; for (DancingLinksNode * ptr = head. l; ptr! = (& Head); ptr = ptr-> L) if (size [ptr-> c] <INF) {INF = size [ptr-> c]; c = ptr-> c;} cover (c);/*** overwrite column c ***/DancingLinksNode * ptr; for (ptr = col [c]. d; ptr! = (& Col [c]); ptr = ptr-> D) {DancingLinksNode * rc; ptr-> R-> L = ptr; for (rc = ptr-> L; rc! = Ptr; rc = rc-> L) cover (rc-> c); ptr-> R-> L = ptr-> L; ans [k] = ptr-> r + 1; if (search (k + 1) return true; ptr-> L-> R = ptr; for (rc = ptr-> R; rc! = Ptr; rc = rc-> R) resume (rc-> c); ptr-> L-> R = ptr-> R;} resume (c ); /*** cancel overwriting column c ***/return false;} int main () {while (scanf ("% d", & m, & n )! = EOF) {init (m, n); for (int I = 0; I <m; ++ I) {int x, j; scanf ("% d ", & x); while (x --) {scanf ("% d", & j); j --; addNode (I, j ); // row I j is column 1} if (! Search (0) puts ("NO") ;}}/* The establishment of the model naturally requires the establishment of all conflicting conditions. Here there are four. 1. counterparts cannot have the same number. 2. the number of Columns cannot be the same. 3. the same block cannot have the same number. In addition to the three obvious constraints, there is also a more important one, that is, 4. each location can have only one number. Therefore, for a 9*9 Sudoku, set the rows as follows: (row label, column label), (row label, number), (column label, number ), (block number, number) each block is 9*9 = 81, with a total of 324 positions. For example, if I want to add a number k in the j column of an I row, then I want to add a row containing four numbers (I, j), (I, k ), (j, k) (block (I, j), k) block (I, j) returns (I, j) if the block label has an initial value, all the initial values are put together and placed in 0th rows. Then, in the 1st-layer loop, the specific values are overwritten only once .. If we can guarantee that the first round of the Loop will inevitably reach this line, we will do this. Otherwise, delete these columns before recursion starts. The previous scheme is proposed only because it is easy to write. */

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.