数独问题(Java版)
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数独问题(Java版)相关的知识,希望对你有一定的参考价值。
题目描述
玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列 均含1-9,不重复。
数独的答案都是唯一的,所以,多个解也称为无解。
本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。
格式要求:
输入9行,每行9个字符,0代表未知,其它数字为已知。
输出9行,每行9个数字表示数独的解。
代码展示
import java.util.Scanner;
public class Main {
static int[][] matrix;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
matrix = new int[9][9];
// 初始化矩阵,0:代表空位
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
matrix[i][j] = sc.nextInt();
}
}
System.out.println("------------------");
dfs(0, 0);
}
// 深度遍历,一行一行开始
public static void dfs(int i, int j) {
// 递归结束,到第10行
if (i == 9) {
printResult();
System.exit(0); // 程序结束,否则一直打印结果,因为递归深度太深
}
// 如果当前 i行 j列 是 0即空位置,则将 1-10分别试着放入空位,假如放入,判断第i行第j列是否存在该数字
if (matrix[i][j] == 0) {
for (int k = 1; k < 10; k++) {
// 如果不存在,则将该数字放入,从该行下一列开始,继续试着填充
// i+(j+1)/9, (j+1)%9 巧妙的实现,遍历一行,遍历完了换到下一行
if (!check(i, j, k)) {
// 如果将当前位置i,j 先初步设置为了 k,试着往下继续递归填数
// 可能遇到某一个位置,不能继续填数了,因为行列有重复,无法填值成功,则当前栈中方法逐步出栈,直到回溯错误的填数位置
matrix[i][j] = k;
dfs(i+(j+1)/9, (j+1)%9);
}
}
// 回溯过程中需要,复位
matrix[i][j] = 0;
} else {
dfs(i+(j+1)/9, (j+1)%9);
}
}
// 检查 i行 j列 是否已存在 num
public static boolean check(int i, int j, int num) {
for (int k = 0; k < 9; k++) {
if (matrix[i][k] == num || matrix[k][j] == num) {
return true;
}
}
return false;
}
// 输出结果
public static void printResult() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(matrix[i][j]+" ");
}
System.out.println();
}
}
}
输入:
0 0 8 0 7 0 6 0 0
0 1 0 5 6 0 0 0 0
0 2 0 0 0 0 0 0 1
0 6 0 0 0 0 0 0 0
5 7 1 0 3 0 4 9 8
0 0 0 0 0 0 0 7 0
4 0 0 0 0 0 0 6 0
0 0 0 0 4 3 0 5 0
0 0 3 0 5 0 2 0 0
输出:
1 3 8 2 7 5 6 4 9
2 1 4 5 6 7 9 8 3
6 2 5 4 8 9 7 3 1
3 6 7 1 9 4 8 2 5
5 7 1 6 3 2 4 9 8
8 4 9 3 2 1 5 7 6
4 5 2 9 1 8 3 6 7
7 9 6 8 4 3 1 5 2
9 8 3 7 5 6 2 1 4
拓展问题
问题描述:
给定数列 a,判断是否可以从中选出若干个数,使他们的和恰好为 k。
例如:
输入:
n=4
a={1,2,4,7}
k=13
输出:
Yes
分析:
由于数列中每个数存在加或者不加两种状态,那么可绘制二叉状态树如下:
因此考虑使用递归算法求解。
代码展示:
import java.util.Scanner;
public class _23_数独问题2 {
static int[] a;
static int k;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
k = sc.nextInt();
a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
if (dfs(0, k))
System.out.println("Yes");
else
System.out.println("No");
}
// 深度遍历
public static boolean dfs(int i, int curSum) {
// 递归结束条件
if (i+1 == a.length) {
return curSum + a[i] == k;
}
// 剪枝,减少不必要的递归,优化效率
// 如果当前未到数组末尾,但是已经满足sum==k || sum > k,直接跳出,返回相应结果
if (curSum >= k) {
return curSum == k;
}
// 对于当前 数可以选择也可以放弃
// 选择走二叉树左分支
if (dfs(i+1, curSum+a[i]))
return true;
// 不选择走有分支
if (dfs(i+1, curSum))
return true;
// 若左右分支都不满足,则回溯时返回 false
return false;
}
}
参考博客 Link
感谢
以上是关于数独问题(Java版)的主要内容,如果未能解决你的问题,请参考以下文章