搜索实现:解决数独有两种思考策略,一种是枚举当前格能填的数字的种数,这里有一优化策略就是先搜索能填入种数小的格子;另一种是考虑处理某一行(列、宫)时,对于某一个没用过的数字,若该行(列、宫)只有一个可行的空白格时,就只能将该数字填入此格中。第二种实现起来略麻烦,此处仅实现第一种策略,并调整搜索顺序进行优化操作,优先搜索能填数字种数较小的格子。
另外,在搜索时,条件判断的效率尤为重要,故分别记录各行、各列、各宫已经出现的数字,这样就可以直接判断该空格填入某数字是否可行。
以POJ2676为例,无调整搜索顺序的优化,用时26ms,调整搜索顺序后用时0ms。
1 //dfs搜索,枚举当前格能填的数字 2 #include <stdio.h> 3 #include <algorithm> 4 using namespace std; 5 const int N = 9; 6 char mp[N+1][N+1]; 7 int row[N+1], col[N+1], squ[N+1]; 8 struct p{ 9 int x, y, z; 10 p(int a = 0, int b = 0, int c = 0) :x(a), y(b), z(c){} 11 bool operator <(const p& m)const { 12 return z < m.z; 13 } 14 }; 15 p pa[N*N+1]; 16 int tot; 17 18 bool dfs(int d) { 19 if (d == tot) return true; 20 21 for(int i = d; i < tot; i++){ 22 int nn = 0, x = pa[i].x, y = pa[i].y; 23 pa[i].z = 0; 24 for(int j = 1; j < 512; j <<= 1) 25 if( !(row[x]&j) && !(col[y]&j) && !(squ[x/3*3+y/3]&j) ) 26 pa[i].z++; 27 } 28 sort(pa+d, pa+tot);//调整搜素顺序!! 29 30 int x = pa[d].x, y = pa[d].y; 31 for(int i = 1; i <= N; i++){ 32 int j = 1 <<(i-1); 33 if(!(row[x]&j) && !(col[y]&j) && !(squ[x/3*3+y/3]&j)){ 34 row[x] ^= j, col[y] ^= j, squ[x/3*3+y/3] ^= j; 35 mp[x][y] = '0'+i; 36 if(dfs(d+1)) return true; 37 row[x] ^= j, col[y] ^= j, squ[x/3*3+y/3] ^= j; 38 } 39 } 40 return false; 41 } 42 43 int main(){ 44 int t; scanf("%d", &t); 45 while(t--){ 46 for(int i = 0; i < 9; i++) 47 for(int j = 0; j < 9; j++) 48 scanf(" %c", &mp[i][j]); 49 50 for(int i = 0; i < N; i++) 51 row[i] = col[i] = squ[i] = 0; 52 tot = 0; 53 54 for(int i = 0; i < N; i++) 55 for(int j = 0; j < N; j++) 56 if(mp[i][j] != '0'){ 57 int idx = mp[i][j]-'1'; 58 row[i] |= 1<<idx, col[j] |= 1<<idx, squ[i/3*3+j/3] |= 1<<idx; 59 } 60 else 61 pa[tot++] = p(i, j); 62 63 for(int i = 0; i < tot; i++){ 64 int nn = 0, x = pa[i].x, y = pa[i].y; 65 for(int j = 1; j < 512; j <<= 1) 66 if( !(row[x]&j) && !(col[y]&j) && !(squ[x/3*3+y/3]&j) ) 67 pa[i].z++; 68 } 69 70 dfs(0); 71 72 for (int i = 0; i < 9; ++i) 73 puts(mp[i]); 74 } 75 return 0; 76 }