POJ 2676 Sudoku
题目链接:http://poj.org/problem?id=2676
数独问题。用dancing links解决。
要注意的就是搜索的时候 要先搜索 那一列中节点最少的,否则时间会很长。
#include <iostream> #include <cstring> #include <cstdio> #include <string> #include <iomanip> using namespace std; int T; #define maxn 9*9*9*4+81*4+10 int L[maxn], R[maxn], D[maxn], U[maxn]; int H[maxn], C[maxn], ans[85], sum[81*4+10]; int mp[10][10]; int head, cnt; struct Node{ int x, y, val; }hmap[9*9*9+10]; void addnode(int x, int y, int val, int h){ int pos1 = 81*0 + (x-1)*9+y; int pos2 = 81*1 + (x-1)*9 + val; int pos3 = 81*2 + (y-1)*9 + val; int pos4 = 81*3 + (((x-1)/3)*3 + (y-1)/3)*9 + val; H[cnt+1] = H[cnt+2] = H[cnt+3] = H[cnt+4] = h; C[cnt+1] = pos1; C[cnt+2] = pos2; C[cnt+3] = pos3; C[cnt+4] = pos4; R[cnt+1] = cnt+2; R[cnt+2] = cnt+3; R[cnt+3] = cnt+4; R[cnt+4] = cnt+1; L[cnt+1] = cnt+4; L[cnt+2] = cnt+1; L[cnt+3] = cnt+2; L[cnt+4] = cnt+3; D[U[pos1]] = cnt+1; D[cnt+1] = pos1; U[cnt+1] = U[pos1]; U[pos1] = cnt+1; D[U[pos2]] = cnt+2; D[cnt+2] = pos2; U[cnt+2] = U[pos2]; U[pos2] = cnt+2; D[U[pos3]] = cnt+3; D[cnt+3] = pos3; U[cnt+3] = U[pos3]; U[pos3] = cnt+3; D[U[pos4]] = cnt+4; D[cnt+4] = pos4; U[cnt+4] = U[pos4]; U[pos4] = cnt+4; sum[pos1]++; sum[pos2]++; sum[pos3]++; sum[pos4]++; cnt+=4; hmap[h].x = x; hmap[h].y = y; hmap[h].val = val; } void init(){ memset(sum, 0, sizeof(sum)); head = 0; cnt = 0; R[head] = 1; L[head] = 81*4; U[head] = head; D[head] = head; for(int i = 1; i <= 81*4; i++){ //头节点。 cnt++; H[cnt] = 0; C[cnt] = i; U[cnt] = cnt; D[cnt] = cnt; if(i == 81*4){ R[cnt-1] = cnt; L[cnt] = cnt-1; R[cnt] = head; } else{ R[cnt-1] = cnt; L[cnt] = cnt-1; } } int h = 0; for(int i = 1; i <= 9; i++){ string temp; cin>>temp; for(int j = 0; j < 9; j++){ if(temp[j] == '0'){ for(int k = 1; k <= 9; k++) addnode(i, j+1, k, ++h); } else{ addnode(i, j+1, int(temp[j]-'0'), ++h); } } } } void remove(int c){ R[L[c]] = R[c]; L[R[c]] = L[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]; sum[C[j]]--; } } } void resume(int c){ R[L[c]] = c; L[R[c]] = c; for(int i = D[c]; i != c; i = D[i]){ for(int j = R[i]; j != i; j = R[j]){ U[D[j]] = j; D[U[j]] = j; sum[C[j]]++; } } } bool dance(int k){ int c = R[head]; if(c == head){ return true; } int min = 99999; for(int i = R[head];i != head; i = R[i]){ if(sum[i]<=min){ min = sum[i]; c = i; } } remove(c); for(int i = D[c]; i != c; i = D[i]){ ans[k] = H[i]; for(int j = R[i]; j != i; j = R[j]) remove(C[j]); if(dance(k+1)) return true; for(int j = L[i]; j != i; j = L[j]) resume(C[j]); } resume(c); return false; } int main(){ scanf("%d", &T); while(T--){ init(); bool flag = dance(0); for(int i = 0; i < 81; i++){ mp[hmap[ans[i]].x][hmap[ans[i]].y] = hmap[ans[i]].val; } for(int i = 1; i <= 9; i++){ for(int j = 1; j <= 9; j++){ printf("%d", mp[i][j]); } printf("\n"); } } return 0; }