Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
数独是根据 9×9 盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含 1−9 ,不重复。每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的。
来源:洛谷 www.luogu.com.cn/problem/P17…
输入格式
一个未填的数独。
8 0 0 0 0 0 0 0 0
0 0 3 6 0 0 0 0 0
0 7 0 0 9 0 2 0 0
0 5 0 0 0 7 0 0 0
0 0 0 0 4 5 7 0 0
0 0 0 1 0 0 0 3 0
0 0 1 0 0 0 0 6 8
0 0 8 5 0 0 0 1 0
0 9 0 0 0 0 4 0 0
输出格式
填好的数独。
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−9 ,不重复。 满足每一行、每一列不重复很简单,但是我们如何表示在每一个粗线宫内不重复呢?
根据例题我们可以看到 3*3 的小格为一个粗线宫, 9×9 的盘面上一共有 9 个粗线宫
我们可以通过该位置的行和列来判断它属于哪一个粗线宫, i/3*3 + j/3 因为每行3个嘛~ , 例如(0,0)它就属于第0个粗线宫, (8,8)就属于第8个粗线宫
我们从 (0,0)位置开始填数,一直往下走 (0,1)、(0,2).....(0,8)、(1,0)、(1,1)....... 当能判断到(9,0)的时候,说明我们已经找到答案了,由于仅有唯一答案,我们找到后直接返回即可。 如果该位置本来就有数字的话,直接往下走去填下一个位置的数,若该位置需要填数字,我们需要对它进行判断,并进行标记和回溯
三、AC 代码:
import java.util.*;
public class Main {
static int[][] map;
static boolean[][] hen, shu, gezi;
public static void main(String[] args) {
Scanner sr = new Scanner(System.in);
// 地图 (将输入为0的位置改变成 1-9 后输出)
map = new int[10][10];
hen = new boolean[10][10]; // 横
shu = new boolean[10][10]; // 竖
gezi = new boolean[10][10]; // 粗线宫
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++) {
map[i][j] = sr.nextInt();
// 当这个位置本来就有数字,需要对它进行标注
if (map[i][j] != 0) {
hen[i][map[i][j]] = true;
shu[j][map[i][j]] = true;
gezi[i / 3 * 3 + j / 3][map[i][j]] = true;
}
}
// 从(0, 0)开始
fun(0, 0);
}
private static void fun(int x, int y) {
if (x == 9) // 输出
{
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++)
System.out.print(map[i][j] + " ");
System.out.println();
}
return;
}
// 换下一行
if (y == 9)
fun(x + 1, 0);
// 本来就有数字
if (map[x][y] != 0) {
fun(x, y + 1);
} else {
// 1-9 的数字都试一下能不能填在这个位置
for (int k = 1; k <= 9; k++)
if (!hen[x][k] && !shu[y][k] && !gezi[x / 3 * 3 + y / 3][k]) {
// 标记并回溯
map[x][y] = k;
hen[x][k] = true;
shu[y][k] = true;
gezi[x / 3 * 3 + y / 3][k] = true;
fun(x, y + 1);
hen[x][k] = false;
shu[y][k] = false;
gezi[x / 3 * 3 + y / 3][k] = false;
map[x][y] = 0;
}
}
}
}
四、总结:
一整个就是一个暴力深搜的大动作😃 主要就是在如何判断这个数字能不能填在该粗线宫内不重复,这里想清楚了,就很简单了,八皇后的案例和这个挺像的