搜索实现:解决数独有两种思考策略,一种是枚举当前格能填的数字的种数,这里有一优化策略就是先搜索能填入种数小的格子;另一种是考虑处理某一行(列、宫)时,对于某一个没用过的数字,若该行(列、宫)只有一个可行的空白格时,就只能将该数字填入此格中。第二种实现起来略麻烦,此处仅实现第一种策略,并调整搜索顺序进行优化操作,优先搜索能填数字种数较小的格子。

另外,在搜索时,条件判断的效率尤为重要,故分别记录各行、各列、各宫已经出现的数字,这样就可以直接判断该空格填入某数字是否可行。

以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 }
View Code

相关文章: