目前最快的数独求解程序 - 实现了Knuth的Dancing Links+Algorithm X算法

目前最快的数独求解程序 - 实现了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 ");
  }
}


你可能感兴趣的:(目前最快的数独求解程序 - 实现了Knuth的Dancing Links+Algorithm X算法)