目前最快的数独求解程序 - 实现了Knuth的Dancing Links+Algorithm X算法
C++语言: 目前最快的数独求解程序 - 实现了Knuth的Dancing Links+Algorithm X算法
//from: http://code.google.com/p/klsudoku/source/checkout
//半瓶墨水修改于 2009 Sept 18
//References
// http://en.wikipedia.org/wiki/Knuth's_Algorithm_X
// http://en.wikipedia.org/wiki/Dancing_Links
// http://en.wikipedia.org/wiki/Exact_cover#Sudoku
#include<iostream>
using namespace std;
#define RR 729
#define CC 324
#define INF 1000000000
int mem1 [ 81 + 1 ];
int mem2 [ 81 + 1 ];
int * mem = mem1;
char ch [ 81 + 1 ];
int cnt [ CC + 1 ];
int scnt = 0; //solution count
struct node {
int r , c;
node * up;
node * down;
node * left;
node * right;
} head , all [ RR * CC + 99 ], row [ RR ], col [ CC ]; int all_t;
inline void link( int r , int c) {
cnt [ c ] ++;
node * t =& all [ all_t ++ ];
t -> r = r;
t -> c = c;
t -> left =& row [ r ];
t -> right = row [ r ]. right;
t -> left -> right = t;
t -> right -> left = t;
t -> up =& col [ c ];
t -> down = col [ c ]. down;
t -> up -> down = t;
t -> down -> up = t;
}
inline void remove( int c) {
node * t , * tt;
col [ c ]. right -> left = col [ c ]. left;
col [ c ]. left -> right = col [ c ]. right;
for( t = col [ c ]. down; t !=& col [ c ]; t = t -> down) {
for( tt = t -> right; tt != t; tt = tt -> right) {
cnt [ tt -> c ] --;
tt -> up -> down = tt -> down;
tt -> down -> up = tt -> up;
}
t -> left -> right = t -> right;
t -> right -> left = t -> left;
}
}
inline void resume( int c) {
node * t , * tt;
for( t = col [ c ]. down; t !=& col [ c ]; t = t -> down) {
t -> right -> left = t;
t -> left -> right = t;
for( tt = t -> left; tt != t; tt = tt -> left) {
cnt [ tt -> c ] ++;
tt -> down -> up = tt;
tt -> up -> down = tt;
}
}
col [ c ]. left -> right =& col [ c ];
col [ c ]. right -> left =& col [ c ];
}
void print_solution( int * m ){
int ans [ 81 ];
for( int i = 1; i <= 81; i ++) {
int t = m [ i ] / 9 % 81;
int val = m [ i ] % 9 + 1;
ans [ t ] = val;
}
for( int i = 0; i < 81; i ++)
printf( "%d" , ans [ i ]);
printf( " \n ");
}
void solve( int k)
{
if( head . right ==& head) { //got one solution
if ( ! scnt) {
memcpy( mem2 , mem1 , sizeof( mem1));
mem = mem2;
}
scnt ++;
return;
}
node * t , * tt;
int min = INF , tc;
for( t = head . right; t !=& head; t = t -> right) {
if( cnt [ t -> c ] < min) {
min = cnt [ t -> c ];
tc = t -> c;
if( min <= 1) break;
}
}
remove( tc);
for( t = col [ tc ]. down; t !=& col [ tc ]; t = t -> down) {
mem [ k ] = t -> r;
t -> left -> right = t;
for( tt = t -> right; tt != t; tt = tt -> right) {
remove( tt -> c);
}
t -> left -> right = t -> right;
solve( k + 1);
if ( scnt >= 2)
return;
t -> right -> left = t;
for( tt = t -> left; tt != t; tt = tt -> left) {
resume( tt -> c);
}
t -> right -> left = t -> left;
}
resume( tc);
return;
}
int main( int argc , char ** argv) {
if ( argc != 2) return 1;
const char *p = argv [ 1 ];
size_t len = strlen(p);
if ( len != 81) return 1;
int i , j , k;
for ( i = 0; i < 81; i ++) {
if (( *p) == '0')
ch [ i ] = '.';
else
ch [ i ] = *p;
p ++;
}
ch [ 81 ] = '\0';
if( ch [ 0 ] == 'e') return 1;
all_t = 1;
memset( cnt , 0 , sizeof( cnt));
head . left =& head;
head . right =& head;
head . up =& head;
head . down =& head;
head . r = RR;
head . c = CC;
for( i = 0; i < CC; i ++) {
col [ i ]. c = i;
col [ i ]. r = RR;
col [ i ]. up =& col [ i ];
col [ i ]. down =& col [ i ];
col [ i ]. left =& head;
col [ i ]. right = head . right;
col [ i ]. left -> right =& col [ i ];
col [ i ]. right -> left =& col [ i ];
}
for( i = 0; i < RR; i ++) {
row [ i ]. r = i;
row [ i ]. c = CC;
row [ i ]. left =& row [ i ];
row [ i ]. right =& row [ i ];
row [ i ]. up =& head;
row [ i ]. down = head . down;
row [ i ]. up -> down =& row [ i ];
row [ i ]. down -> up =& row [ i ];
}
for( i = 0; i < RR; i ++) {
int r = i / 9 / 9 % 9;
int c = i / 9 % 9;
int val = i % 9 + 1;
if( ch [ r * 9 + c ] == '.'|| ch [ r * 9 + c ] == val + '0') {
link( i , r * 9 + val - 1);
link( i , 81 + c * 9 + val - 1);
int tr = r / 3;
int tc = c / 3;
link( i , 162 +( tr * 3 + tc) * 9 + val - 1);
link( i , 243 + r * 9 + c);
}
}
for( i = 0; i < RR; i ++) {
row [ i ]. left -> right = row [ i ]. right;
row [ i ]. right -> left = row [ i ]. left;
}
solve( 1);
printf( " \n ");
if ( scnt > 1 ){
print_solution( mem1);
print_solution( mem2);
printf( " \n 2 or mroe solutions found \n ");
} else if ( scnt == 1) {
print_solution( mem1);
printf( " \n one solution found \n ");
} else {
printf( " \n NO solution \n ");
}
}
//半瓶墨水修改于 2009 Sept 18
//References
// http://en.wikipedia.org/wiki/Knuth's_Algorithm_X
// http://en.wikipedia.org/wiki/Dancing_Links
// http://en.wikipedia.org/wiki/Exact_cover#Sudoku
#include<iostream>
using namespace std;
#define RR 729
#define CC 324
#define INF 1000000000
int mem1 [ 81 + 1 ];
int mem2 [ 81 + 1 ];
int * mem = mem1;
char ch [ 81 + 1 ];
int cnt [ CC + 1 ];
int scnt = 0; //solution count
struct node {
int r , c;
node * up;
node * down;
node * left;
node * right;
} head , all [ RR * CC + 99 ], row [ RR ], col [ CC ]; int all_t;
inline void link( int r , int c) {
cnt [ c ] ++;
node * t =& all [ all_t ++ ];
t -> r = r;
t -> c = c;
t -> left =& row [ r ];
t -> right = row [ r ]. right;
t -> left -> right = t;
t -> right -> left = t;
t -> up =& col [ c ];
t -> down = col [ c ]. down;
t -> up -> down = t;
t -> down -> up = t;
}
inline void remove( int c) {
node * t , * tt;
col [ c ]. right -> left = col [ c ]. left;
col [ c ]. left -> right = col [ c ]. right;
for( t = col [ c ]. down; t !=& col [ c ]; t = t -> down) {
for( tt = t -> right; tt != t; tt = tt -> right) {
cnt [ tt -> c ] --;
tt -> up -> down = tt -> down;
tt -> down -> up = tt -> up;
}
t -> left -> right = t -> right;
t -> right -> left = t -> left;
}
}
inline void resume( int c) {
node * t , * tt;
for( t = col [ c ]. down; t !=& col [ c ]; t = t -> down) {
t -> right -> left = t;
t -> left -> right = t;
for( tt = t -> left; tt != t; tt = tt -> left) {
cnt [ tt -> c ] ++;
tt -> down -> up = tt;
tt -> up -> down = tt;
}
}
col [ c ]. left -> right =& col [ c ];
col [ c ]. right -> left =& col [ c ];
}
void print_solution( int * m ){
int ans [ 81 ];
for( int i = 1; i <= 81; i ++) {
int t = m [ i ] / 9 % 81;
int val = m [ i ] % 9 + 1;
ans [ t ] = val;
}
for( int i = 0; i < 81; i ++)
printf( "%d" , ans [ i ]);
printf( " \n ");
}
void solve( int k)
{
if( head . right ==& head) { //got one solution
if ( ! scnt) {
memcpy( mem2 , mem1 , sizeof( mem1));
mem = mem2;
}
scnt ++;
return;
}
node * t , * tt;
int min = INF , tc;
for( t = head . right; t !=& head; t = t -> right) {
if( cnt [ t -> c ] < min) {
min = cnt [ t -> c ];
tc = t -> c;
if( min <= 1) break;
}
}
remove( tc);
for( t = col [ tc ]. down; t !=& col [ tc ]; t = t -> down) {
mem [ k ] = t -> r;
t -> left -> right = t;
for( tt = t -> right; tt != t; tt = tt -> right) {
remove( tt -> c);
}
t -> left -> right = t -> right;
solve( k + 1);
if ( scnt >= 2)
return;
t -> right -> left = t;
for( tt = t -> left; tt != t; tt = tt -> left) {
resume( tt -> c);
}
t -> right -> left = t -> left;
}
resume( tc);
return;
}
int main( int argc , char ** argv) {
if ( argc != 2) return 1;
const char *p = argv [ 1 ];
size_t len = strlen(p);
if ( len != 81) return 1;
int i , j , k;
for ( i = 0; i < 81; i ++) {
if (( *p) == '0')
ch [ i ] = '.';
else
ch [ i ] = *p;
p ++;
}
ch [ 81 ] = '\0';
if( ch [ 0 ] == 'e') return 1;
all_t = 1;
memset( cnt , 0 , sizeof( cnt));
head . left =& head;
head . right =& head;
head . up =& head;
head . down =& head;
head . r = RR;
head . c = CC;
for( i = 0; i < CC; i ++) {
col [ i ]. c = i;
col [ i ]. r = RR;
col [ i ]. up =& col [ i ];
col [ i ]. down =& col [ i ];
col [ i ]. left =& head;
col [ i ]. right = head . right;
col [ i ]. left -> right =& col [ i ];
col [ i ]. right -> left =& col [ i ];
}
for( i = 0; i < RR; i ++) {
row [ i ]. r = i;
row [ i ]. c = CC;
row [ i ]. left =& row [ i ];
row [ i ]. right =& row [ i ];
row [ i ]. up =& head;
row [ i ]. down = head . down;
row [ i ]. up -> down =& row [ i ];
row [ i ]. down -> up =& row [ i ];
}
for( i = 0; i < RR; i ++) {
int r = i / 9 / 9 % 9;
int c = i / 9 % 9;
int val = i % 9 + 1;
if( ch [ r * 9 + c ] == '.'|| ch [ r * 9 + c ] == val + '0') {
link( i , r * 9 + val - 1);
link( i , 81 + c * 9 + val - 1);
int tr = r / 3;
int tc = c / 3;
link( i , 162 +( tr * 3 + tc) * 9 + val - 1);
link( i , 243 + r * 9 + c);
}
}
for( i = 0; i < RR; i ++) {
row [ i ]. left -> right = row [ i ]. right;
row [ i ]. right -> left = row [ i ]. left;
}
solve( 1);
printf( " \n ");
if ( scnt > 1 ){
print_solution( mem1);
print_solution( mem2);
printf( " \n 2 or mroe solutions found \n ");
} else if ( scnt == 1) {
print_solution( mem1);
printf( " \n one solution found \n ");
} else {
printf( " \n NO solution \n ");
}
}
|
|