DFS:解数独
问题描述:
输入一个9∗9的数独,其中未填数的部分用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 }
总结:
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.数独看起来很麻烦, 其实代码还挺简洁的. 当初一个上午理解不了递归的实现, 不过现在看来思路就是一个字, 简单. 我们遇到什么困难, 也不要怕! 微笑着面对他! 消除恐惧的最好办法就是面对恐惧! 坚持,才是胜利! 加油,奥利给!