很强大,比一般的回溯法快了很多。ZOJ 2580的瞬间解出。调试的时候把注释都去掉了—_—
明天试试POJ的那个16×16的数独看....(那个还能被称为数独么—_—)
#include <cstdio> #define MAXW 324 #define MAXN 3240 #define INF 800 #define ROW 81 #define COL 162 #define BLOCK 243 int C[MAXN+10], L[MAXN+10], R[MAXN+10], U[MAXN+10], D[MAXN+10], S[MAXW+10], O[81], save[MAXW+10]; int flag; void remove(const int &c) { L[R[c]] = L[c]; R[L[c]] = R[c]; for (int i = D[c]; i != c; i = D[i]) { for (int j = R[i]; j != i; j = R[j]) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[C[j]]; } } } void resume(const int &c) { for (int i = U[c]; i != c; i = U[i]) { for (int j = L[i]; j != i; j = L[j]) { ++S[C[j]]; U[D[j]] = j; D[U[j]] = j; } } L[R[c]] = c; R[L[c]] = c; } void dfs(const int &k) { if(R[0] == 0) { for(int j = 0; j < 81; j++) { printf("%d", O[j]); if((j+1)%9 == 0) { printf("/n"); } } flag = 1; return; } int s = INF, c; for (int t = R[0]; t != 0; t = R[t]) { if (S[t] < s) { s = S[t]; c = t; } } remove(c); for (int i = D[c]; i != c; i = D[i]) { int x = (i-324-1)/4; O[x/9] = x%9 + 1; for (int j = R[i]; j != i; j = R[j]) { remove(C[j]); } dfs(k + 1); for (int k = L[i]; k != i; k = L[k]) { resume(C[k]); } if(flag == 1) { break; } } resume(c); } void insert_node(int& cnt, int col, int head, int& tail) { C[cnt] = col; S[col]++; U[cnt] = U[col]; D[U[col]] = cnt; D[cnt] = col; U[col] = cnt; R[tail] = cnt; L[cnt] = tail; R[cnt] = head; L[head] = cnt; tail = cnt; cnt++; } int main(int argc, char* argv[]) { int T, i, j, ccnt, cnt, col, head, tail, num, digt, x, y, len; scanf("%d", &T); while(T--) { ccnt = 324; len = 0; flag = 0; for(i = 0; i <= ccnt; i++) { L[i] = i-1; R[i] = i+1; U[i] = D[i] = i; S[i] = 0; } L[0] = ccnt; R[ccnt] = 0; cnt = ccnt+1; for(i = 0; i < 729; i++) { digt = i % 9 + 1; num = i / 9; x = num / 9; y = num % 9; head = tail = cnt; col = num + 1; insert_node(cnt, col, head, tail); col = ROW + x*9 + digt; insert_node(cnt, col, head, tail); col = COL + y*9 + digt; insert_node(cnt, col, head, tail); col = BLOCK + (x/3*3+y/3)*9 + digt; insert_node(cnt, col, head, tail); } for(i = 0; i < 9; i++) { for(j = 0; j < 9; j++) { scanf("%1d", &x); if(x != 0) { int t = i*9 + j; O[t] = x; remove(++t); save[len++] = t; remove(t = ROW+i*9+x); save[len++] = t; remove(t = COL+j*9+x); save[len++] = t; remove(t = BLOCK+(i/3*3+j/3)*9+x); save[len++] = t; } } } dfs(0); for(i = len-1; i >= 0; i--) { resume(save[i]); } } return 0; }