http://poj.org/problem?id=3074
POJ 3074 Sudoku
Effect: Solving size of 9 x 9 Sudoku problem
Analysis: For each row, each column, each house, numbers 1, 2. . . 9 are required to appear once and only once,
It can be converted to exact cover problem, with dancing chain solutions
The model:
Number of rows is 9 * 9 * 9, the number of Independent i-th row j-th column stores the state of discharge of the digital k (i * 9 + j) * 9 + k rows in FIG.
Number of columns is 9 * 9 * 9 + 9 + 9 + 9 * 9 * 9,
The first of a 9 * 9 grid is representative of whether or not the i-filled,
Ensure that the number in the line with a second 9 * 9 and the only appears once
The third 9 * 9 ensure that the digital and each column only appears once
The fourth 9 * 9 ensure that each house of unique numbers appear more than once
#include<stdio.h>
#include<string.h>
const int MAX_COLOUMN = 81 + 9 * 9 + 9 * 9 + 9 * 9 + 2; // Number of columns appears most
const int MAX_ROW = 81 * 9 + 2; // Number of columns appears most
int cnt [MAX_COLOUMN]; // cnt number [i] i th column 1 Statistics
int most,coloumn;
bool ans [MAX_ROW]; // ans storage of the final selected row
// dancing chain node
struct Point
{
int up, down, left, right; // on the up, down, left, right
int coloumn; // the point where the column headings
int row; // Industry Standard
}node[MAX_ROW*MAX_COLOUMN+MAX_COLOUMN];
// Initialize the dance chain information is empty
void init(int m)
{
int i;
for(i=0;i<=m;i++)
{
node[i].down=i;
node[i].up = i;
node[i].coloumn=i;
node[i].left=i-1;
node[i].right=i+1;
cnt[i]=0;
}
node[0].left = m;
node[m].right = 0;
}
void remove (int c) // remove all elements of row 1 column where the c
{
node[node[c].right].left=node[c].left;
node[node[c].left].right=node[c].right;
int t,tt;
for (t = node [c] .down;! t = c; t = node [t] .down) // delete left to right from top to bottom on each nonzero element of the row of the column information
{
for (tt = node [t] .right; tt = t;! tt = node [tt] .right) // delete the non-zero elements in the row
{
cnt[node[tt].coloumn]--;
node[node[tt].down].up = node[tt].up;
node[node[tt].up].down = node[tt].down;
}
}
}
void resume (int c) // restore all the elements located on the row 1 column c
{
int t,tt;
for (t = node [c] .up;! t = c; t = node [t] .up) // restore from the bottom row from left to right and this column 1 where c
{
for(tt=node[t].left;tt!=t;tt=node[tt].left)
{
cnt[node[tt].coloumn]++;
node[node[tt].up].down=tt;
node[node[tt].down].up=tt;
}
}
node[node[c].right].left=c;
node[node[c].left].right=c;
}
The number of bool dfs (int k) // k is already selected row
{
int i,j;
if(k>=most)return false;
if (node [coloumn] .right == coloumn) // currently dancing chain is already empty
{
if(k<most)
most = k;
return true;
}
int t = coloumn+1;
int c;
// Select a minimum current column matrix
for(i=node[coloumn].right;i!=coloumn;i=node[i].right)
{
if(cnt[i]<t)
{
c=i;t=cnt[i];
if(t==1)break;
}
}
remove (c); // delete all the rows c 1 where the column
When top to bottom, left to right // delete, restore from bottom to top, right to left
for(i = node[c].down;i!=c;i=node[i].down)
{
for(j=node[i].right;j!=i;j=node[j].right)
{
remove(node[j].coloumn);
}
ans[node[j].row]=true;
if(dfs(k+1))
{
return true;
}
ans[node[j].row]=false;
for(j=node[j].left;j!=i;j=node[j].left)
{
resume(node[j].coloumn);
}
}
resume(c);
return false;
}
bool graph[MAX_ROW][MAX_COLOUMN];
void addrow(int i,int j,int k)
{
int curr = (i*9+j)*9+k;
graph[curr][(i*9+j)]=true;
graph[curr][81+i*9+k]=true;
graph[curr][81+81+j*9+k]=true;
int tr = i/3;
int tc = j/3;
graph[curr][81+81+81+(tr*3+tc)*9+k]=true;
}
char str[MAX_ROW];
int main()
{
int N,M,i,j,k;
while(scanf("%s",str)!=EOF)
{
if(strcmp(str,"end")==0)break;
N=81*9;
M = 9*9+9*9+9*9+9*9;
coloumn = M;
int cur = coloumn + 1; // current node number
init(coloumn);
memset(graph,0,sizeof(graph));
for(i=0;i<9;i++)
for(j=0;j<9;j++)
{
if(str[i*9+j]=='.')
{
for (k = 0; k <9; k ++) // through each color
{
addrow(i,j,k);
}
continue;
}
k = str[i*9+j]-'1';
addrow(i,j,k);
}
for(i=0;i<N;i++)
{
int start = cur; // record the start point of the i-th column number
int pre = cur; // record the left of the current column 1 first numbers 1
for(j=0;j<M;j++)
{
// scanf("%d",&n);
if (graph [i] [j]) // dance chain only non-zero element insertion
{
int pos = j;
node[cur].up = node[pos].up;
node[node[pos].up].down = cur;
node[cur].down = pos;
node[pos].up = cur;
cnt [pos] ++; // number of the column 1 +1
node[cur].coloumn = pos;
node[cur].left = pre;
node[pre].right = cur;
node[cur].right = start;
node[start].left=cur;
node[cur].row = i;
pre=cur++;
}
}
}
most = N + 1; // record requires a minimum number of lines selected
memset(ans,false,sizeof(ans));
dfs(0);
// printf("Yes, I found it\n");
for(i=0;i<81;i++)
for(j=0;j<9;j++)
if(ans[i*9+j])
{
printf("%d",j+1);
break;
}
printf("\n");
}
return 0;
}