一、思路
dfs进行试探,如果失败就进行回溯,若找到一组解就进行返回最后输出。
进行剪枝:
- 利用3个数组进行判断在某行某列某方格中 这个数到底被标记没有,如果别标记那么就不能选这个数。
- 特别注意的是如何对3*3的小方格里面的1-9进行标记
- 首先我们将大方格分成9个3*3的小方格
- i,j代表在大方格中的位置,下标从0到8, 我们让a=i/3, b = j /3
可以从图中得出 K = 3 * a + b = 3 * (i / 3) + j / 3;
这就是3*3小方格的下标,我们就可将9个3*3的小方格里面的1-9进行标记
二、代码
import java.util.Scanner;
public class POJ_2676 {
static int t;
static int[][] G = new int[10][10];
static boolean[][] row = new boolean[10][10]; //row[i][x] 代 表第i行的x被标记没有 true为被标记
static boolean[][] col = new boolean[10][10]; //col[i][x] 代 表第i列的x被标记没有
static boolean[][] grid = new boolean[10][10]; //grid[k][x] 代 表第k个3*3的小格子的x被标记没有
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
t = sc.nextInt();
while (t-- > 0) {
clear();//清空下row col grid ok
for (int i = 0; i < 9; i++) {
String str = sc.next();
for (int j = 0; j < 9; j++) {
G[i][j] = str.charAt(j) - '0';
if (G[i][j] != 0) {
//进行标记
int k = 3 *(i / 3) + j / 3;
row[i][G[i][j]] = true;
col[j][G[i][j]] = true;
grid[k][G[i][j]] = true;
}
}
}
dfs(0,0);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(G[i][j]);
}
System.out.println();
}
}
}
static boolean ok; //查看是否找到一种可能
static void dfs(int x, int y) {
if (x == 9) {
ok = true; //找到一组解
return; //已经到第10行了 超出了
}
if (G[x][y] != 0){
//代表该位上已经有数,直接搜下一个
if (y + 1 == 9) {
dfs(x + 1,0);
} else {
dfs(x, y + 1);
}
} else {
//k代表第几个方格
int k = 3 * (x / 3) + y / 3;
//枚举 1-9 这个9个数 看那个能放在这个位置上
for (int i = 1; i <= 9; i++) {
if (!row[x][i] && !col[y][i] && !grid[k][i]) {
//3个条件都满足
G[x][y] = i;
row[x][i] = true;
col[y][i] = true;
grid[k][i] = true;
if (y + 1 == 9) {
dfs(x + 1,0);
} else {
dfs(x, y + 1);
}
if (ok) return; //如果找到一组解 就不回溯
//回溯
G[x][y] = 0;
row[x][i] = false;
col[y][i] = false;
grid[k][i] = false;
}
}
}
}
static void clear() {
for (int i = 0; i <= 9; i++) {
for (int j = 0; j <= 9; j++) {
ok = false;
row[i][j] = false;
col[i][j] = false;
grid[i][j] = false;
G[i][j] = 0; //注意清空下原图
}
}
}
}