POJ 2676
设置三个标记数组,分别是行的,列的和小正方型的。 行列比较好处理,至于小正方形,我刚开始是直接把每个格子遍历一遍,然后算出他们分别在哪一个小正方形内,最后存在一个数组里。这个方法虽然比较麻烦但是很好想,也不会花太多时间。做完之后学长又说了另一个好一些的办法。每个小正方形的编号k(1~9)恰好就等于(i - 1) / 3 * 3 + (j - 1) / 3 + 1。 有了这个式子就简单多了。(关于这个式子的推导见参考博客,感谢!)然后就是普通的深搜加回溯。由于只需要得到一个满足的结果,所以我设置了一个flag来进行剪枝。不知道这个办法好不好,还请多指教。
参考博客:http://blog.csdn.net/lyy289065406/article/details/6647977 感谢!!!
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int map[15][15]; int visrow[15][15]; int viscol[15][15]; int vissq[15][15]; int flag = 0; void dfs(int x, int y, int num0) { if(flag) return; //剪枝,找出了解就直接退出即可 int i, j; if(num0 == 0 && !flag) { flag = 1; for(i = 1; i <= 9; i++) { for(j = 1; j <= 9; j++) { printf("%d", map[i][j]); } printf("\n"); } return; } if(map[x][y] == 0) { for(i = 1; i <= 9; i++) { if(visrow[x][i] == 0 && viscol[y][i] == 0 && vissq[(x-1)/3*3+(y-1)/3+1][i] == 0) { map[x][y] = i; visrow[x][i] = 1; viscol[y][i] = 1; vissq[(x-1)/3*3+(y-1)/3+1][i] = 1; if(y != 9) dfs(x, y + 1, num0 - 1); else dfs(x + 1, 1, num0 - 1); map[x][y] = 0; visrow[x][i] = 0; viscol[y][i] = 0; vissq[(x-1)/3*3+(y-1)/3+1][i] = 0; } } } else { if(y != 9) dfs(x, y + 1, num0); else dfs(x + 1, 1, num0); } } int main () { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int t; scanf("%d", &t); getchar(); while(t--) { int i, j, num0 = 0; char ch; int n; for(i = 1; i <= 9; i++) { for(j = 1; j <= 9; j++) { visrow[i][j] = 0; viscol[i][j] = 0; vissq[i][j] = 0; } } for(i = 1; i <= 9; i++) { for(j = 1; j <= 9; j++) { scanf("%c", &ch); n = ch - '0' ; map[i][j] = n; if(map[i][j] == 0) num0++; visrow[i][map[i][j]] = 1; viscol[j][map[i][j]] = 1; vissq[(i-1)/3*3+(j-1)/3 + 1][map[i][j]] = 1; } getchar(); } flag = 0; dfs(1, 1, num0); } return 0; }