DFS:解数独

问题描述:

输入一个99的数独,其中未填数的部分用0表示,1−9表示当前这个位置已经填了这个数。

输出一个9*9的填满了数的数独。(满足限制要求的任意一组解即可)

样例输入 1

0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

样例输出 1

8 1 2 7 5 3 6 4 9 
9 4 3 6 8 2 1 7 5 
6 7 5 4 9 1 2 8 3 
1 5 4 2 3 7 8 9 6 
3 6 9 8 4 5 7 2 1 
2 8 7 1 6 9 5 3 4 
5 2 1 9 7 4 3 6 8 
4 3 8 5 2 6 9 1 7 
7 9 6 3 1 8 4 5 2
 1 #include<cstdio>
 2 #define rep(i,a,b) for(int i=a;i<b;i++)
 3 bool row[10][10], col[10][10], box[10][10];
 4 int grid[10][10];
 5 bool flag = 0;
 6 void dfs(int n) {
 7     if (n > 80) {
 8         flag = 1;
 9         rep(i, 0, 9) {
10             rep(j, 0, 9)
11                 printf("%d ", grid[i][j]);
12             printf("\n");
13         }
14         return;
15     }
16     if (!flag) {
17         int x = n / 9, y = n % 9, t = y / 3 + x / 3 * 3;
18         if (!grid[x][y]) {
19             rep(i, 1, 10) {
20                 if (!row[x][i] && !col[y][i] && !box[t][i]) {
21                     grid[x][y] = i;
22                     row[x][i] = 1;
23                     col[y][i] = 1;
24                     box[t][i] = 1;
25                     dfs(n + 1);
26                     grid[x][y] = 0;
27                     row[x][i] = 0;
28                     col[y][i] = 0;
29                     box[t][i] = 0;
30                 }
31             }
32         }
33         else dfs(n + 1);
34     }
35 }
36 int main() {
37     rep(i, 0, 9)rep(j, 0, 9) {
38         scanf("%d", &grid[i][j]);
39         int t = j / 3 + i / 3 * 3;
40         if (grid[i][j]) {
41             row[i][grid[i][j]] = 1;
42             col[j][grid[i][j]] = 1;
43             box[t][grid[i][j]] = 1;
44         }
45     }
46     dfs(0);
47 }
View Code

总结:

1.DFS递归函数中,选好函数的形参非常重要. 这里我只用了int n,也就是要填的第n个数(0<=n<=80), 同时全局变量维护3个判断可填的bool数组. 小技巧:用整数除模运算建立第n格到row,col,box的映射, 通过row[i][k]记录第i行有没有填过数k, col与box的bool数组同理.

2.开二维数组可以time-space trade-off, 比每次调用判断函数循环进行(xing)行(hang)列宫判断要快(我就是被这个搞得第一次<OJ>T掉了OTL)

3.如果只要最先找到的一个结果, 可以在完成时用flag标记;  如果想获得全部结果, 不需要flag.

4.数独看起来很麻烦, 其实代码还挺简洁的. 当初一个上午理解不了递归的实现, 不过现在看来思路就是一个字, 简单. 我们遇到什么困难, 也不要怕! 微笑着面对他! 消除恐惧的最好办法就是面对恐惧! 坚持,才是胜利! 加油,奥利给!

posted @ 2021-01-09 08:26  _dwt  阅读(74)  评论(0)    收藏  举报