数独是一个我们都非常熟悉的经典游戏,运用计算机我们可以很快地解开数独难题,现在有一些简单的数独题目,请编写一个程序求解。
如有多解,输出一个解
//当然还是回溯,但是故意不用递归,代码略长,笔试中不推荐我这种做法了,除非更简单实现的时间复杂度达不到要求 /* * 7 0 0 0 0 0 6 3 0 * 0 0 2 0 3 0 0 7 4 * 0 6 8 1 0 4 0 0 0 * 4 0 0 0 0 1 3 9 0 * 9 5 0 3 0 0 4 0 0 * 2 0 7 5 0 0 0 6 0 * 0 4 3 0 9 0 0 0 6 * 0 0 0 0 1 7 0 0 0 * 0 0 0 8 0 0 2 0 9 * * * 7 1 4 9 5 2 6 3 8 * 5 9 2 6 3 8 1 7 4 * 3 6 8 1 7 4 9 5 2 * 4 8 6 7 2 1 3 9 5 * 9 5 1 3 8 6 4 2 7 * 2 3 7 5 4 9 8 6 1 * 8 4 3 2 9 5 7 1 6 * 6 2 9 4 1 7 5 8 3 * 1 7 5 8 6 3 2 4 9 * * * 4 0 0 0 5 0 6 0 0 * 0 0 8 7 0 0 0 9 4 * 9 0 6 0 8 0 0 0 0 * 0 8 0 0 4 1 0 7 0 * 0 1 0 0 0 0 5 4 0 * 7 0 0 9 3 5 0 0 0 * 8 3 0 0 0 2 0 0 7 * 0 9 1 0 0 7 0 0 2 * 0 0 0 8 0 0 9 3 0 * * 4 7 3 1 5 9 6 2 8 * 1 5 8 7 2 6 3 9 4 * 9 2 6 4 8 3 7 5 1 * 3 8 5 6 4 1 2 7 9 * 6 1 9 2 7 8 5 4 3 * 7 4 2 9 3 5 8 1 6 * 8 3 4 5 9 2 1 6 7 * 5 9 1 3 6 7 4 8 2 * 2 6 7 8 1 4 9 3 5 * * * 0 0 9 0 0 0 0 3 6 * 3 0 0 0 7 2 0 0 0 * 0 7 0 0 0 5 0 0 8 * 0 0 0 8 0 0 4 0 0 * 0 0 3 4 1 0 0 6 0 * 0 1 0 0 0 0 0 0 5 * 0 0 4 0 0 0 6 7 0 * 0 0 0 0 0 4 1 5 0 * 9 0 0 0 0 0 0 0 0 * * 5 2 9 1 4 8 7 3 6 * 3 4 8 6 7 2 5 9 1 * 6 7 1 9 3 5 2 4 8 * 2 9 6 8 5 3 4 1 7 * 8 5 3 4 1 7 9 6 2 * 4 1 7 2 9 6 3 8 5 * 1 8 4 5 2 9 6 7 3 * 7 6 2 3 8 4 1 5 9 * 9 3 5 7 6 1 8 2 4 */ import java.util.*; import static java.lang.System.in; import static java.lang.System.out; public class Sudoku { static class Range{ int row, col, setIndex; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Range range = (Range) o; return row == range.row && col == range.col && setIndex == range.setIndex; } @Override public int hashCode() { return Objects.hash(row, col, setIndex); } Range(int row, int col, int setIndex){ this.row = row; this.col = col; this.setIndex = setIndex; } } public static void main(String[] args) { Scanner scanner = new Scanner(in); int[][] arr = new int[9][9]; for(int row = 0; row < 9; row++){ for(int col = 0; col < 9; col++){ arr[row][col] = scanner.nextInt(); } } Range[] save = new Range[81]; List<Range> record = new ArrayList<>(); int pos = 0; boolean breakAble; while (true){ breakAble = true; for(int row = 0; row < 9; row++){ for(int col = 0; col < 9; col++){ if (arr[row][col] == 0) { breakAble = false; Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); for (int i = 0; i < 9; i++) { set.remove(arr[row][i]); set.remove(arr[i][col]); } for (int i = (row / 3) * 3; i < (row / 3) * 3 + 3; i++) { for (int j = (col / 3) * 3; j < (col / 3) * 3 + 3; j++) { set.remove(arr[i][j]); } } if (set.size() == 1) { arr[row][col] = set.toArray(new Integer[0])[0]; record.add(new Range(row, col, 0)); } else if (set.size() > 1) { if (pos > 0 && (save[pos - 1].row == row && save[pos - 1].col == col)) { save[pos - 1].setIndex++; if(save[pos - 1].setIndex >= set.size()){ pos--; int[] r = backtrace(pos, arr, save, record); row = r[0]; col = r[1]; }else { arr[row][col] = set.toArray(new Integer[0])[save[pos - 1].setIndex]; } } else { save[pos++] = new Range(row, col, 0); arr[row][col] = set.toArray(new Integer[0])[save[pos - 1].setIndex]; } } else { //set size == 0 int[] r = backtrace(pos, arr, save, record); row = r[0]; col = r[1]; } } } } if(breakAble){ break; } } for(int i = 0; i < 9; i++){ for(int j = 0; j < 9; j++){ out.print(arr[i][j] + " "); } out.println(); } } private static int[] backtrace(int pos, int[][] arr, Range[] save, List<Range> record){ int row = save[pos - 1].row; int col = save[pos - 1].col; arr[row][col] = 0; for(int i = row; i < 9; i++){ for(int j = 0; j < 9; j++){ if(i*9+j > (row*9+col) && record.contains(new Range(i, j, 0))){ arr[i][j] = 0; record.remove(new Range(i, j, 0)); } } } if(col == 0){ row--; col = 8; }else{ col--; } return new int[]{row, col}; } }
//我觉得我写得比较简洁明了 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int[][] a = new int[9][9]; for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) a[i][j] = sc.nextInt(); dfs(a, 0); for (int[] b : a) { for (int c : b) System.out.print(c + " "); System.out.println(); } } } public static boolean dfs(int[][] a, int id) { if (id == 81) return true; int m = id / 9; int n = id % 9; if(a[m][n]==0){ for (int i = 1; i < 10; i++) { if (!numberIsOK(a, m, n, i)) continue; a[m][n] = i; if (dfs(a, id + 1)) return true; a[m][n] = 0; } } else return dfs(a, id+1); return false; } public static boolean numberIsOK(int[][] a, int m, int n, int t) { for (int i = 0; i < 9; i++) { if (a[m][i] == t || a[i][n] == t) //横竖都不存在重复 return false; } for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { if (a[m / 3 * 3 + i][n / 3 * 3 + j] == t) return false; } return true; } }
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int[][] a = new int[9][9];
while(sc.hasNext()) {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
a[i][j] = sc.nextInt();
}
}
dfs(a,0,0);
}
sc.close();
}
static int count;
private static void dfs(int[][] a, int x, int y) {
// TODO Auto-generated method stub
if(x == 9) {//结束
print(a);
System.exit(0);
}
if(a[x][y] == 0) {//如果该位置没有数字
for(int i = 1; i <= 9; i++) {
boolean res = check(a,x,y,i);//检查
if(res) {
a[x][y] = i;
dfs(a,x+(y+1)/9,(y+1)%9);
}
}
a[x][y] = 0;//回溯
}else {//有数字 填下一行
dfs(a,x+(y+1)/9,(y+1)%9);
}
}
private static boolean check(int[][] a, int x, int y, int num) {
// TODO Auto-generated method stub
for(int i = 0; i < 9; i++) {//检查行
if(a[x][i] == num) return false;
}
for(int i = 0; i < 9; i++) {//检查列
if(a[i][y] == num) return false;
}
for(int i = x/3*3; i < (x/3+1)*3; i++) {//检查九宫格
for(int j = y/3*3; j < (y/3+1)*3; j++) {
if(a[i][j] == num) return false;
}
}
return true;
}
private static void print(int[][] a) {
// TODO Auto-generated method stub
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(j == 8) {
System.out.println(a[i][j]);
}else {
System.out.print(a[i][j]+" ");
}
}
}
}
}