使用DFS求解数独(Sudoku)问题
1.题目描述
问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个粗线宫内的数字均含1-9,并且不重复。
输入:
包含已知数字的9X9盘面数组[空缺位以数字0表示]
输出:
完整的9X9盘面数组
示例:
输入:
0 9 2 4 8 1 7 6 3 4 1 3 7 6 2 9 8 5 8 6 7 3 5 9 4 1 2 6 2 4 1 9 5 3 7 8 7 5 9 8 4 3 1 2 6 1 3 8 6 2 7 5 9 4 2 7 1 5 3 8 6 4 9 3 8 6 9 1 4 2 5 7 0 4 5 2 7 6 8 3 1
输出:
5 9 2 4 8 1 7 6 3 4 1 3 7 6 2 9 8 5 8 6 7 3 5 9 4 1 2 6 2 4 1 9 5 3 7 8 7 5 9 8 4 3 1 2 6 1 3 8 6 2 7 5 9 4 2 7 1 5 3 8 6 4 9 3 8 6 9 1 4 2 5 7 9 4 5 2 7 6 8 3 1
2.思路精要
该题可以用DFS来求解,步骤如下:
- (1)对于每个值为0的格子,从1到9尝试,填入一个暂时满足条件的值。
- (2)填写下一个格子(从左到右,从上到下),如果下一个格子能填写数字就继续进行。否则回溯。
3.具体代码
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { // 初始化数独 int[][] sd = new int[9][9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { sd[i][j] = scanner.nextInt(); } } // 填充数独 dfs(sd, 0, 0); // 打印数独 for (int[] row : sd) { for (int i = 0; i < 9; i++) { System.out.print(row[i]); if (i != 8) { System.out.print(" "); } } System.out.println(); } } } private static boolean dfs(int[][] sd, int i, int j) { // (9,0)坐标 if (i == 9) { return true; } if (sd[i][j] == 0) { for (int k = 1; k <= 9; k++) { sd[i][j] = k; if (check(sd, i, j) && dfs(sd, j == 8 ? i + 1 : i, j == 8 ? 0 : j + 1)) { return true; } } sd[i][j] = 0;// 回溯 return false; } else { return dfs(sd, j == 8 ? i + 1 : i, j == 8 ? 0 : j + 1); } } private static boolean check(int[][] sd, int i, int j) { // 同行 for (int k = 0; k < 9; k++) { if (k != j && sd[i][k] == sd[i][j]) { return false; } } // 同列 for (int k = 0; k < 9; k++) { if (k != i && sd[k][j] == sd[i][j]) { return false; } } // 同九宫 int up = i / 3 * 3; int left = j / 3 * 3; for (int k = up; k < up + 3; k++) { for (int l = left; l < left + 3; l++) { if ((k != i || l != j) && sd[k][l] == sd[i][j]) { return false; } } } return true; } }