回溯法解决数独问题
数独
http://www.nowcoder.com/questionTerminal/2b8fa028f136425a94e1a733e92f60dd
问题分析
数独问题,可以拆分成两个子问题,一个是放置数字,一个是校验九宫格是否合法。
后者比较简单,对于前者这种穷举类的问题,一般采用回溯法来解决。
对于每一个待放置数字的位置,我们从1到9挨个往里面放,如果1-9以有一个数字合法的话,就移动到下一个待放置数字的位置,如果不合法,就回退到上一个待放置的位置。
具体操作代码解释的很清楚了。
import java.util.Scanner;
public class shudu {
/*
* 5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9
* */
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//初始化数组
int[][] board = new int[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
board[i][j] = sc.nextInt();
}
}
solve(board);
//按要求输出结果
for (int[] i : board) {
for (int m = 0; m < 9; m++) {
if (m == 8) {
System.out.println(i[m]);
} else {
System.out.print(i[m] + " ");
}
}
}
}
public static void solve(int[][] board) {
backtrack(board, 0, 0);
}
public static boolean backtrack(int[][] board, int i, int j) {
//走到了这一行的末尾,换行
if (j == 9) {
return backtrack(board, i + 1, 0);
}
//走到了第十行,说明前9行匹配成功,返回true。
if (i == 9) return true;
//如果这个数字不是0,跳过。
if (board[i][j] != 0) return backtrack(board, i, j + 1);
//在这个位置挨个放数字
for (int num = 1; num <= 9; num++) {
//如果这个位置放num不合法,就继续。
if (!check(board, i, j, num)) continue;
board[i][j] = num;
//如果接下来都合法,就返回true。
if (backtrack(board, i, j + 1)) return true;
//恢复现场
board[i][j] = 0;
}
//1-9都不行。
return false;
}
public static boolean check(int[][] board, int r, int c, int num) {
//检验当前位置如果放上num这个数字是不是合法的。
for (int i = 0; i < 9; i++) {
if (board[i][c] == num) return false;
if (board[r][i] == num) return false;
//判断小九宫格
if (board[(r / 3) * 3 + i / 3][(c / 3) * 3 + i % 3] == num) return false;
}
return true;
}
}
查看25道真题和解析