问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个3X3粗线宫内的数字均含1-9,并且不重复。
例如:
输入
输出
数据范围:输入一个 9*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
import java.util.Scanner; import java.util.ArrayList; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { // 创建数独棋盘 int[][] suduqp = new int[9][9]; ArrayList<int[]> zeroList = new ArrayList<>(); Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNextInt()) { // 注意 while 处理多个 case for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { int number = in.nextInt(); suduqp[i][j] = number; // 提取空位 if (number == 0) zeroList.add(new int[]{i, j}); } } } // 填充方法 play(suduqp, zeroList, 0); // 打印填充好的棋盘 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { System.out.print(suduqp[i][j] + " "); } System.out.println(); } } public static boolean play(int[][] suduqp, ArrayList<int[]> zeroList, Integer times) { // 如果次数超过集合数,说明已经完成填充 if (times >= zeroList.size()) return true; // 先定位 int[] position = zeroList.get(times); int x = position[0]; int y = position[1]; // 判断是否可以填充数字,九个数字 for (int j = 1; j <= 9; j++) { if (isPrimeNumber(j, suduqp, x, y)) { // 可以填充,则先填充,并找下一个 suduqp[x][y] = j; // 这里 times 不能习惯性用 ++, // 因为会赋值当前 times,导致回溯后,无法正确却找到位置 boolean type = play(suduqp, zeroList, times + 1); if (type) return true; // 失败则回溯 suduqp[x][y] = 0; } } return false; } public static boolean isPrimeNumber(Integer number, int[][] suduqp, Integer x, Integer y) { // 判断行 x 固定 for (int i = 0; i < 9; i++) { if (suduqp[x][i] == number) return false; } // 判断列 y 固定 for (int i = 0; i < 9; i++) { if (suduqp[i][y] == number) return false; } // 判断九宫格 int row = x / 3 * 3, col = y / 3 * 3; for (int i = row; i < row + 3; i++) { for (int j = col; j < col + 3; j++) { if (suduqp[i][j] == number) return false; } } return true; } }
import java.util.*; public class Main { public static Stack<Integer> stackI = new Stack<>(); public static Stack<Integer> stackJ = new Stack<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[][] data = new int[9][9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { data[i][j] = sc.nextInt(); } } sudu(data); for (int[] datum : data) { for (int d : datum) { System.out.print(d + " "); } System.out.println(); } } private static void sudu(int[][] data) { // 回溯法求解 Map<Integer, Integer> map = new LinkedHashMap<>(); for (int i = 0; i < 9; i++) { map.put(i, 0); } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (data[i][j] == 0) { map.put(i, map.get(i) + 1); } } } List<String> strTmp = new ArrayList<>(); map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(v -> strTmp.add(v.toString())); map.clear(); for (int i = 0; i < 9; i++) { String[] str_s = strTmp.get(i).split("="); map.put(Integer.parseInt(str_s[0]), Integer.parseInt(str_s[1])); } for (Integer i : map.keySet()) { for (int j = 0; j < 9; j++) { if (data[i][j] == 0) { addData(data, i, j, 1); } } } } private static void addData(int[][] data, int i, int j, int k) { if (k > 9) { int ITmp = stackI.pop(); int JTmp = stackJ.pop(); int kTmp = data[ITmp][JTmp] + 1; data[ITmp][JTmp] = 0; data[i][j] = 0; addData(data, ITmp, JTmp, kTmp); addData(data, i, j, 1); return; } boolean flag = true; for (; k <= 9; k++) { data[i][j] = k; if (checkisOK(data, i, j)) { stackI.push(i); stackJ.push(j); flag = false; break; } } if (flag) { // i, j 插不进去 ,出栈 int ITmp = stackI.pop(); int JTmp = stackJ.pop(); int kTmp = data[ITmp][JTmp] + 1; data[ITmp][JTmp] = 0; data[i][j] = 0; addData(data, ITmp, JTmp, kTmp); addData(data, i, j, 1); } } // 判断行、列、块是否满足插入 private static boolean checkisOK(int[][] data, int i, int j) { for (int k = 0; k < 9; k++) { if (k != j && data[i][j] == data[i][k]) { return false; } if (k != i && data[i][j] == data[k][j]) { return false; } } int row = i / 3 * 3; int col = j / 3 * 3; for (int k = row; k < row + 3; k++) { for (int l = col; l < col + 3; l++) { if (k == i && l == j) { continue; } if (data[k][l] == data[i][j]) { return false; } } } return true; } }
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNextInt()) { // 注意 while 处理多个 case int[][] db = new int[10][10];//保存原始数据 List<int[]> arr = new ArrayList<>();//记录0元素的位置 for (int i = 1; i <= 9; i++) { for (int j = 1; j <= 9; j++) { db[i][j] = in.nextInt(); if ( db[i][j] == 0){ arr.add(new int[]{i,j}); } } } dfs(arr, db); //打印 for (int i = 1; i <= 9; i++) { for (int j = 1; j <= 9; j++) { System.out.print(db[i][j]+" "); } System.out.println(); } } } private static boolean dfs(List<int[]> arr, int[][] db) { for (int j = 0; j < arr.size(); j++) { int hang = arr.get(j)[0]; int lie =arr.get(j)[1]; //1-9去计算是否符合 for (int i = 1; i <= 9; i++) { if (check(db, hang, lie,i)){ db[hang][lie] = i; List<int[]> temp = new ArrayList<>(); temp.addAll(arr); temp.remove(j); if (dfs(temp,db)){ return true; }else { db[hang][lie] = 0;//回溯 } } } return false; } return true; } //行,列,3*3判断 private static boolean check(int[][] db,int x,int y,int current){ for (int i = 1; i <= 9; i++) { //行 if (db[x][i] == current)return false; //列 if (db[i][y] == current)return false; } //3*3 1 4 int hang = (x-1)/3 *3 +1; //3*3的起始行 int lie = (y-1)/3 *3 +1; //3*3的起始列 for (int i = hang; i < hang+3; i++) { for (int j = lie; j < lie+3; j++) { if (db[i][j] == current){ return false; } } } return true; } }
import java.util.ArrayList; import java.util.List; import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { final int N = 9; Scanner in = new Scanner(System.in); int[][] board = new int[N][N]; List<int[]> empty = new ArrayList<>(); boolean[][] rowFlag = new boolean[N][10]; boolean[][] columnFlag = new boolean[N][10]; boolean[][][] squareFlag = new boolean[3][3][10]; int[] done = new int[]{0}; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { int value = in.nextInt(); board[i][j] = value; if (value == 0) { empty.add(new int[]{i, j}); } else { rowFlag[i][value] = true; columnFlag[j][value] = true; squareFlag[i/3][j/3][value] = true; } } } in.close(); dfs(board, empty, rowFlag, columnFlag, squareFlag, 0, done); } private static void dfs(int[][] board, List<int[]> empty, boolean[][] rowFlag, boolean[][] columnFlag, boolean[][][] squareFlag, int index, int[] done) { if (index == empty.size()) { done[0] = 1; for (int[] arr : board) { for (int x : arr) { System.out.print(x + " "); } System.out.println(); } return; } int[] arr1 = empty.get(index); int x1 = arr1[0], y1 = arr1[1]; for (int value = 1; value <= 9 && done[0] == 0; value++) { if (rowFlag[x1][value] || columnFlag[y1][value] || squareFlag[x1/3][y1/3][value]) { continue; } rowFlag[x1][value] = columnFlag[y1][value] = squareFlag[x1/3][y1/3][value] = true; board[x1][y1] = value; dfs(board, empty, rowFlag, columnFlag, squareFlag, index+1, done); rowFlag[x1][value] = columnFlag[y1][value] = squareFlag[x1/3][y1/3][value] = false; board[x1][y1] = 0; } } }
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 定义一个二维数组,用于存放数独 int[][] sudo = new int[9][9]; // 获取输入的数独矩阵,并加入到数组中 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { sudo[i][j] = in.nextInt(); } } // 开始sudo游戏 playSudoGame(sudo); // 输出游戏结果 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (j >= 0 && j < 8) { System.out.print(sudo[i][j] + " "); } else if (j == 8) { System.out.print(sudo[i][j]); } } // 一行遍历完,换行 System.out.println(); } } /** * 开始数独游戏. */ private static boolean playSudoGame(int[][] sudo) { // 依次进行遍历,找到数组中为0的位置,进行游戏规则判断 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (sudo[i][j] != 0) { // 遍历位置不为0,则跳过该位置,继续遍历下一个, continue; } // 遍历位置为0,将数字1-9依次填入该位置,通过游戏规则判断填入的数字是否符合规范,如符合则填入该数字 for (int m = 1; m <= 9; m++) { // 判断填充的数字是否符合规范,规范则进行将数字填入数独矩阵位置处 if (isPassGameNorm(sudo, i, j, m)) { sudo[i][j] = m; // 进行递归调用,继续在填入数字矩阵后的新矩阵进行遍历下一个0的位置; if (playSudoGame(sudo)) { // 遍历后返回true,则表示填写的数字存在解,则返回true return true; } else { // 如果没有合适的,就进行回溯 sudo[i][j] = 0; } } } // 1-9 9个数字都尝试完成,但没有找到可以填写的正确结果,则无解,返回false return false; } } // 遍历完都没有返回false,则表示找到了正确的结果,及返回true return true; } /** * 数独游戏规范,判断填入的数字是否符合规范,符合规范返回true,反之返回false. */ private static boolean isPassGameNorm(int[][] sudo, int i, int j, int m) { // 判断所在位置的行是否存在该数字,存在则不规范,不存在则规范 for (int x = 0; x < 9; x++) { if (sudo[i][x] == m) { return false; } } // 判断所在位置的列是否存在该数字,存在则不规范,不存在则规范 for (int x = 0; x < 9; x++) { if (sudo[x][j] == m) { return false; } } // 计算所在位置3x3宫格遍历的其实位置和终点位置 int row = (i / 3) * 3; int col = (j / 3) * 3; // 判断所在位置存在的3x3宫格内是否存在该数字,存在则不规范,不存在则规范 for (int x = row; x < row + 3; x++) { for (int y = col; y < col + 3; y++) { if (sudo[x][y] == m) { return false; } } } // 当没有出现不符合规范时,返回true return true; } }
import java.util.Scanner; import java.util.ArrayList; import java.util.List; import java.util.Arrays; /** * @author YXQ * @create 2022/8/3 17:34 */ //思路:每个0的位置可以填1-9的数字,然后填上之后,检验这个数字是否有效, // 若有效,继续填写下一个为0的位置,若1-9都填写完了还是无效,则证明这样填无效 可能是上一层错了(回溯)也可能是此数独无解 // 验证有效的方式:三个维度有效:在x,y,以及3x3的小框内不存在*****重复*****数字,这个验证方式很重要 // 如上分析 这道题就和n皇后题差不多了 public class Main { // ****************第一种************************************* // public static void main(String[] args) { // Scanner sc=new Scanner(System.in); // int[][] arr=new int[9][9]; // for(int i=0;i<9;i++){ // for (int j=0;j<9;j++){ // arr[i][j]=sc.nextInt(); // } // sc.nextLine(); // } // dfs(arr); // for (int i=0;i<9;i++){ // for (int j=0;j<9;j++){ // System.out.print(arr[i][j]+" "); // } // System.out.println(); // } // } // public static boolean dfs(int[][] arr){ // for (int i=0;i<9;i++){ // for(int j=0;j<9;j++){ // if(arr[i][j]!=0) continue; // for(int k=1;k<=9;k++){ // if(isValid(arr,i,j,k)){ // arr[i][j]=k; // if(dfs(arr))return true; // arr[i][j]=0; // } // } // return false; // } // } // return true; // } // ****************************************第二种********** // public static void main(String[] args) { // Scanner sc=new Scanner(System.in); // int[][] arr=new int[9][9]; // List<int[]>list=new ArrayList<>(); // for(int i=0;i<9;i++){ // for (int j=0;j<9;j++){ // arr[i][j]=sc.nextInt(); // if(arr[i][j]==0)list.add(new int[]{i,j}); // } // sc.nextLine(); // } // dfs(arr,list,0); // for (int i=0;i<9;i++){ // for (int j=0;j<9;j++){ // System.out.print(arr[i][j]+" "); // } // System.out.println(); // } // } // public static boolean dfs(int[][] arr,List<int[]>list,int index){ // if(index>=list.size())return true; // for (int i=1;i<=9;i++){ // int x=list.get(index)[0]; // int y=list.get(index)[1]; // if(isValid(arr,x,y,i)){ // // System.out.println("x:"+x+"y:"+y); // // System.out.println(i); // arr[x][y]=i; // if(dfs(arr,list,index+1))return true; // arr[x][y]=0; // } // } // return false; // } // // ***********************************************第三种*********** public static void main(String[] args) { Scanner sc=new Scanner(System.in); int[][] arr=new int[9][9]; List<int[]>list=new ArrayList<>(); for(int i=0;i<9;i++){ for (int j=0;j<9;j++){ arr[i][j]=sc.nextInt(); if(arr[i][j]==0)list.add(new int[]{i,j}); } sc.nextLine(); } dfs(arr,list,0); for (int i=0;i<9;i++){ for (int j=0;j<9;j++){ System.out.print(res[i][j]+" "); } System.out.println(); } } static int[][]res=new int[9][9]; public static void dfs(int[][] arr,List<int[]>list,int index){ if(index>=list.size()){ for (int i=0;i<arr.length;i++){ res[i]= Arrays.copyOf(arr[i],arr[i].length); } return; }; for (int i=1;i<=9;i++){ int x=list.get(index)[0]; int y=list.get(index)[1]; if(isValid(arr,x,y,i)){ // System.out.println("x:"+x+"y:"+y); // System.out.println(i); arr[x][y]=i; dfs(arr,list,index+1); arr[x][y]=0; } } } public static boolean isValid(int[][] arr,int i,int j,int k){ // 判断一行是否重复 for(int x=0;x<9;x++){ if(arr[x][j]==k)return false; } for (int y=0;y<9;y++){ if(arr[i][y]==k)return false; } int row=i/3*3,col=j/3*3; for (int x=row;x<row+3;x++){ for(int y=col;y<col+3;y++){ if(arr[x][y]==k)return false; } } return true; } }
import java.util.*; public class Main { public static int[][] sudo = new int[9][9];//创建数组 public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); while(sc.hasNext()){ for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ sudo[i][j]=sc.nextInt();//创建数独 } } if(backTracking(sudo)){ for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ if(j==8){ //最后一位数需要换行输出 System.out.println(sudo[i][j]); }else{ System.out.print(sudo[i][j]+" "); } } } } } } public static boolean backTracking(int[][] sudo){ for(int i=0;i<9;i++){ for(int j=0;j<9;j++){//遍历数组 if(sudo[i][j]!=0){//如果不需要填数字直接continue continue; } for(int k=1;k<=9;k++){//循环填数字 if(isValid(i,j,k,sudo)){//判断填入数字是否符合要求 sudo[i][j]=k;//填数字 if(backTracking(sudo)){//递归 return true; } sudo[i][j]=0;//回溯 } } return false;//如果没有符合要求的数字返回false } } return true; } public static boolean isValid(int row,int col,int k,int[][] sudo){ for(int i=0;i<9;i++){//检查行 if(sudo[row][i]==k){ return false; } } for(int i=0;i<9;i++){//检查列 if(sudo[i][col]==k){ return false; } } int startRow = (row/3)*3; int endCol = (col/3)*3; for(int i=startRow;i<startRow+3;i++){//检查九宫格 for(int j=endCol;j<endCol+3;j++){ if(sudo[i][j]==k){ return false; } } } return true; } }
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { // 记录每行 每列 每个方格该位置的元素是否出现 private static boolean[][] row; private static boolean[][] col; private static boolean[][][] board; private static int[][] matrix = new int[9][9]; private static boolean flag = false; // 空缺列表 private static List<int[]> list; public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNextInt()) { // 注意 while 处理多个 case for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ matrix[i][j] = in.nextInt(); } } row = new boolean[9][10]; col = new boolean[9][10]; board = new boolean[3][3][10]; list = new ArrayList<>(); for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ if(matrix[i][j] == 0){ list.add(new int[]{i,j}); continue; } // 记录该元素已经在该行 该列 该单元格出现 row[i][matrix[i][j]] = col[j][matrix[i][j]] = board[i/3][j/3][matrix[i][j]] = true; } } dfs(0); for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ System.out.print(matrix[i][j]); if(j < 8) System.out.print(" "); } System.out.println(); } } } // 回溯 public static void dfs(int cnt){ if(cnt == list.size()){ flag = true; return ; } int[] cur = list.get(cnt); int i = cur[0], j = cur[1]; for(int digit=1;digit<=9 && !flag;digit++){ // 枚举(i,j)填写的数字 if(!row[i][digit] && !col[j][digit] && !board[i/3][j/3][digit]){ row[i][digit] = col[j][digit] = board[i/3][j/3][digit] = true; // 将数组中该位置的元素改为digit matrix[i][j] = digit; dfs(cnt+1); //matrix[i][j] = 0; row[i][digit] = col[j][digit] = board[i/3][j/3][digit] = false; } } } }
import java.util.*; public class Main { public static boolean correct(int[][] martix, int[] arr, int val) { int row = arr[0], col = arr[1]; for (int i = 0; i < 9; i++) { if (martix[row][i] == val || martix[i][col] == val) { return false; } } int x = row / 3, y = col / 3; for (int i = x * 3; i < x * 3 + 3; i++) { for (int j = y * 3; j < y * 3 + 3; j++) { if (martix[i][j] == val) { return false; } } } return true; } public static boolean dfs(int[][] martix, List<int[]> pl, int index) { if (index == pl.size()) { return true; } int[] arr = pl.get(index); for (int i = 1; i <= 9; i++) { if (correct(martix, arr, i)) { martix[arr[0]][arr[1]] = i; if (dfs(martix, pl, index + 1)) { return true; } martix[arr[0]][arr[1]] = 0; } } return false; } public static void main(String[] args) throws Exception { Scanner in = new Scanner(System.in); int[][] martix = new int[9][9]; List<int[]> pl = new ArrayList<int[]>(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { martix[i][j] = in.nextInt(); if (martix[i][j] == 0) { pl.add(new int[] { i, j }); } } } if (dfs(martix, pl, 0)) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { System.out.print(martix[i][j] + " "); } System.out.println(); } } } }
import java.util.Scanner; /** * dfs解数独 * 从左往右,从上往下遍历每个格子 * 在空格处 循环1-9,检查能不能放,能放->放入,继续递归。不能放->回溯到上一个空格 * 当最后一行遍历完了,说明格子都填满了,直接结束。 */ public class Main { //定义数独数组,9行9列 public static int[][] arr = new int[9][9]; public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNextInt()){ //初始化数独数组 for (int i = 0;i < 9;i++){ for (int j = 0; j < 9;j++){ arr[i][j] = sc.nextInt(); } } //调用dfs方法 dfs(0,0); //打印结果 for (int i = 0;i < 9;i++){ for (int j = 0; j < 9;j++){ System.out.print(arr[i][j]+" "); } System.out.println(); } } } /** * dfs填数独 * @param x 当前的行 * @param y 当前的列 * @return */ public static boolean dfs(int x,int y){ //x的范围是0-8,如果x到9,说明数组已经全填完了,直接结束,返回true if (x == 9){ return true; } //y的范围是0-8,如果到9,说明当前行已经遍历完所有列了,跳到下一行 if (y == 9){ return dfs(x+1,0); } //当前格子已经填了数字了,跳到下一个格子 if (arr[x][y] != 0){ return dfs(x,y+1); } //走到这一步说明当前这个格子是空的,还要判断一下是否能填数字 //循环1-9 for (int i = 1;i <= 9;i++){ //当前格子能填数字i if (check(x,y,i)){ //填上 arr[x][y] = i; //继续递归,如果能成功,返回true if (dfs(x,y+1)){ return true; } //如果走到这一步,说明后面的某个格子填入失败了,回溯到这一步,把当前格子改回空格,继续循环 arr[x][y] = 0; } } //如果循环完了没有数字能填入,结束当前dfs,返回false return false; } /** * 检查当前这个格子能不能填数字num * @param x 当前行 * @param y 当前列 * @param num 准备填入的数字 * @return */ public static boolean check(int x ,int y , int num){ //循环遍历,拿传入的数字与每行,每列比较 for (int i = 0;i < 9 ;i++){ //与当前行其他数字比较 if (arr[x][i] == num){ return false; } //与当前列其他数字比较 if (arr[i][y] == num){ return false; } } //循环遍历,那传入的数字与每个小九宫格里的数字比较 for (int i = (x/3)*3;i < (x/3)*3+3 ; i++){ for (int j = (y/3)*3; j < (y/3)*3+3;j++){ if (arr[i][j] == num){ return false; } } } return true; } }
import java.util.Scanner; public class Main { static boolean[][] rowBit = new boolean[9][9]; static boolean[][] colBit = new boolean[9][9]; static boolean[][] boxBit = new boolean[9][9]; public static void main(String args[]) { int[][] question = new int[9][9]; Scanner scan = new Scanner(System.in); for (int row = 0; row < 9; row++) { for (int col = 0; col < 9; col++) { int t = scan.nextInt(); question[row][col] = t; if (t == 0) continue; setBit(row, col, t, true); } } if (!solveSudoku(question, 0, 0)) System.out.println("无解"); for (int row = 0; row < 9; row++) { for (int col = 0; col < 9; col++) { System.out.print(question[row][col]+" "); } System.out.println(); } } public static boolean solveSudoku(int[][] q, int i, int j) { for (; i < 9; i++) { for (j = 0;j < 9; j++) { // 找到空位 if (q[i][j] == 0) { // 找一个可以填的数填入,递归 for (int test = 1; test < 10; test++) { if (!rowBit[i][test-1] && !colBit[j][test-1] && !boxBit[getBox(i, j)][test-1]) { q[i][j] = test; setBit(i, j, test, true); if (solveSudoku(q, i, j)) return true; q[i][j] = 0; setBit(i, j, test, false); } // 没有任何数可以填入 if (test == 9) return false; } } } } return true; } public static int getBox(int row, int col) { return (row / 3) * 3 + col / 3; } public static void setBit(int i, int j, int test, boolean f) { rowBit[i][test-1] = f; colBit[j][test-1] = f; boxBit[getBox(i, j)][test-1] = f; } }
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[][] grid = new int[9][9]; boolean[][] rowMap = new boolean[9][9]; boolean[][] colMap = new boolean[9][9]; boolean[][] gridMap = new boolean[9][9]; for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { grid[i][j] = sc.nextInt(); if(grid[i][j] != 0) { rowMap[i][grid[i][j]-1] = true; colMap[j][grid[i][j]-1] = true; gridMap[(i/3)*3+j/3][grid[i][j]-1] = true; } } } dfs(0, 0, grid, rowMap, colMap, gridMap); for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { System.out.print(grid[i][j]); if(j != 8) System.out.print(" "); } System.out.println(); } } public static boolean dfs(int row, int col, int[][] grid, boolean[][] rowMap, boolean[][] colMap, boolean[][] gridMap) { if(row == 9) return true; if(col == 9) return dfs(row+1, 0, grid, rowMap, colMap, gridMap); if(grid[row][col] != 0) return dfs(row, col+1, grid, rowMap, colMap, gridMap); for(int k = 1; k <= 9; k++) { if(!rowMap[row][k-1] && !colMap[col][k-1] && !gridMap[(row/3)*3+col/3][k-1]) { grid[row][col] = k; rowMap[row][k-1] = true; colMap[col][k-1] = true; gridMap[(row/3)*3+col/3][k-1] = true; if(dfs(row, col+1, grid, rowMap, colMap, gridMap)) return true; grid[row][col] = 0; rowMap[row][k-1] = false; colMap[col][k-1] = false; gridMap[(row/3)*3+col/3][k-1] = false; } } return false; } }
import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; public class Main { public static void main(String[] args) throws IOException { int[][] numbers = new int[9][9]; BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int[][] indexs = new int[81][2]; int nextRow = 0; char c; for (int i = 0, j = 0; j < 9; ) { c = (char) in.read(); if (c == ' ') continue; if (c == '\n' || c == '\r') { j++; i = 0; continue; } numbers[j][i] = Integer.valueOf(c + ""); if (numbers[j][i] == 0) { indexs[nextRow][0] = j; indexs[nextRow][1] = i; nextRow++; } i++; } int num; boolean isOK; int[] vals; int m, n; for (int i = 0; i < nextRow; ) { num = numbers[indexs[i][0]][indexs[i][1]]; numbers[indexs[i][0]][indexs[i][1]] = 0; vals = new int[10]; for (int j = 0; j < 9; j++) { vals[numbers[indexs[i][0]][j]] = 1; } for (int j = 1; j < 10; j++) { if (vals[j] == 0 && num < j) { isOK = true; for (int k = 0; k < 9; k++) { //横列 if (j == numbers[indexs[i][0]][k]) { isOK = false; break; } //竖列 if (j == numbers[k][indexs[i][1]]) { isOK = false; break; } //粗线框要唯一!!! //粗线框要唯一!!! //粗线框要唯一!!! //0:00, 1:01, 2:02 //4:10, 5:11, 6:12 //7:20, 8:21, 9:22 m = k / 3 + (indexs[i][0] / 3) * 3; n = k % 3 + (indexs[i][1] / 3) * 3; if (j == numbers[m][n]) { isOK = false; break; } } if (isOK) { numbers[indexs[i][0]][indexs[i][1]] = j; break; } } } if (numbers[indexs[i][0]][indexs[i][1]] == 0) { i--;//回溯 } else { i++; } } StringBuffer sb = new StringBuffer(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { sb.append(numbers[i][j]); sb.append(" "); } sb.append("\n"); } sb.delete(sb.length() - 1, sb.length()); System.out.println(sb); } }
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Hj44 { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNextInt()) { // 注意 while 处理多个 case Integer[][] mat = new Integer[9][9]; for(int i=0;i<9;i++) for(int j=0;j<9;j++) mat[i][j] = in.nextInt(); //更新相关点的信息 //Integer[][] 第0行是位置 第一行到第四行是 同一行 同一列 同一个方块儿 最后一行是可能的选择 // System.out.println("Starting..."); mat = solveFunc(mat); printFunc(mat); } } private static Integer[][] solveFunc(Integer[][] mat ) { Stack<Integer[][]> matStack = new Stack<>(); matStack.push(mat); int depth = 0; while(!matStack.isEmpty()){ Integer[][] newMat = matStack.pop(); HashMap<Integer, Integer[][]> connectArray = construct(newMat); if (connectArray == null) continue; //推理函数 boolean success = kenanFunc(connectArray, newMat); if(!success) continue; if(success && isCorrect(newMat)){ return newMat; } int minKey = findMin(connectArray); if(minKey == -1) continue; Integer[] myChoice = connectArray.get(minKey)[4]; depth += 1; for (Integer newChoice:myChoice) { // System.out.print("depth is "+ depth); // System.out.println(" Position is " + minKey + ",newChoice is " + newChoice); matStack.push(copyFunc(newMat, minKey, newChoice)); } } return mat; } private static boolean kenanFunc(HashMap<Integer, Integer[][]> connectArray, Integer[][] mat) { //初始化推理 Iterator<Integer> iterator = connectArray.keySet().iterator(); while(!connectArray.isEmpty() && iterator.hasNext()){ Integer nowKey= iterator.next(); Integer[][] infos = connectArray.get(nowKey); Integer[] myChoice = infos[4]; for (int i = 0; i < 3; i++) { replaceFunc(connectArray, nowKey, infos[i+1]); } if(connectArray.get(nowKey)[4].length==1){ Integer[] pos = infos[0]; mat[pos[0]][pos[1]] = infos[4][0]; removeKey(connectArray,convert(infos[0])); iterator = connectArray.keySet().iterator(); }else if(connectArray.get(nowKey)[4].length==0) return false; else if((connectArray.get(nowKey)[4].length-1) > connectArray.get(nowKey)[1].length+connectArray.get(nowKey)[2].length+connectArray.get(nowKey)[3].length) return false; } return true; } private static Integer[][] copyFunc(Integer[][] mat, Integer minKey, Integer newChoice) { Integer[][] newMat = new Integer[9][9]; for (int d = 0; d < mat.length; d++) { newMat[d] = Arrays.copyOf(mat[d], 9); } int[] tempPos = convert(minKey); newMat[tempPos[0]][tempPos[1]] = newChoice.intValue(); return newMat; } private static boolean isCorrect(Integer[][] mat) { if(haveZero(mat)) return false; //某列的元素 HashSet<Integer> integers = new HashSet(); for (int i = 0; i < mat.length; i++) { integers.addAll(Arrays.asList(mat[i])); if(integers.size()!=9) return false; else integers.clear(); } //某列的元素 for (int j = 0; j < mat[0].length; j++) { for (int i = 0; i < mat.length; i++) { integers.add(mat[i][j]); } if(integers.size()!=9) return false; else integers.clear(); } integers.clear(); //某个方块的元素 for (int xSec = 0; xSec < 3; xSec++) { for (int ySec = 0; ySec < 3; ySec++) { int [] sec1 = {0,1,2,9,10,11,18,19,20}; for (int d = 0; d < sec1.length;d++){ sec1[d] = sec1[d] + xSec*27 + ySec *3; } for (int g:sec1) { int[] pos = convert(g); int i = pos[0],j=pos[1]; integers.add(mat[i][j]); } if(integers.size()!=9) return false; else integers.clear(); } } return true; } private static void printFunc(Integer[][] mat) { //输出结果 for(int i=0;i<9;i++) { System.out.print(mat[i][0]); for (int j = 1; j < 9; j++) { System.out.print(" "); System.out.print(mat[i][j]); } if(i<8) System.out.println(""); } } private static void removeKey(HashMap<Integer, Integer[][]> connectArray, Integer myKey) { for (int i = 1; i < 4; i++) { for(Integer youKey:connectArray.get(myKey)[i]){ Integer[][] tempHash = connectArray.get(youKey); ArrayList<Integer> temp = new ArrayList(Arrays.asList(tempHash[i])); if(temp.contains(myKey)){ temp.remove(myKey); tempHash[i] =temp.toArray(new Integer[temp.size()]); connectArray.put(youKey, tempHash); } } } connectArray.remove(myKey); } public static HashMap<Integer, Integer[][]> construct(Integer[][] mat){ HashMap<Integer, Integer[][]> connectArray= new HashMap(128); for(int i=0;i<9;i++) for(int j=0;j<9;j++) if(mat[i][j] == 0){ Integer[][] t = findInfo(mat, convert(new Integer[]{i,j})); connectArray.put(convert(t[0]), t); } return connectArray; } public static Integer[][] findInfo(Integer[][] mat, int start){ ArrayList<Integer> colNeigh = new ArrayList<>(); ArrayList<Integer> rowNeigh = new ArrayList<>(); ArrayList<Integer> sqaureNeigh = new ArrayList<>(); HashSet<Integer> pValues = new HashSet(); pValues.addAll(Arrays.asList(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9})); int[] point = convert(start); int x = point[0], y = point[1]; //一行的零点 for(int i = x, j = 0;j<9;j++){ if(mat[i][j] == 0 && j!=y){ colNeigh.add(convert(new Integer[]{i,j})); }else if(pValues.contains(mat[i][j])){ pValues.remove(mat[i][j]); } } //一列的元素 for(int i = 0, j = y;i<9;i++){ if(mat[i][j] == 0 && i!=x){ rowNeigh.add(convert(new Integer[]{i,j})); }else if(pValues.contains(mat[i][j])){ pValues.remove(mat[i][j]); } } //一个方块的元素 int xSec = point[0]/3, ySec = point[1]/3; int [] sec1 = {0,1,2,9,10,11,18,19,20}; for (int d = 0; d < sec1.length;d++){ sec1[d] = sec1[d] + xSec*27 + ySec *3; } for (int g:sec1) { int[] pos = convert(g); int i = pos[0],j=pos[1]; if(mat[i][j] == 0 && !(i == x && j == y)){ sqaureNeigh.add(g); }else if(pValues.contains(mat[i][j])){ pValues.remove(mat[i][j]); } } //加入HashMap中 Integer[][] info = new Integer[5][]; info[0] = new Integer[]{x,y}; info[1] = rowNeigh.toArray(new Integer[rowNeigh.size()]); info[2] = colNeigh.toArray(new Integer[colNeigh.size()]); info[3] = sqaureNeigh.toArray(new Integer[sqaureNeigh.size()]); info[4] = pValues.toArray(new Integer[pValues.size()]); return info; } public static int findMin(HashMap<Integer, Integer[][]>connectArray){ int minKey = -1; int minValue = Integer.MAX_VALUE; for (Integer key:connectArray.keySet()) { if(connectArray.get(key)[4].length<minValue){ minValue = connectArray.get(key)[4].length; minKey = key; } } return minKey; } public static void replaceFunc(HashMap<Integer, Integer[][]>connectArray, Integer myKey, Integer[] infosn) { int flagPosCount = 1; //一行的邻居 Integer[] myChoice = connectArray.get(myKey)[4]; for(Integer youKey: infosn){ Integer[] yourChoice = connectArray.get(youKey)[4]; if(Arrays.equals(myChoice, yourChoice)) { flagPosCount++; } } if(flagPosCount==myChoice.length){ for(Integer you: infosn){ Integer[] yourChoice = connectArray.get(you)[4]; if(! Arrays.equals(myChoice, yourChoice)){ Integer[] yourChoiceAlter = alterFunc(yourChoice,myChoice); Integer[][] temp = connectArray.get(you); temp[4] = yourChoiceAlter; connectArray.replace(you, temp); } } } } public static Integer[] alterFunc(Integer[] more, Integer[] less) { HashSet<Integer> temp = new HashSet(); temp.addAll(Arrays.asList(more)); for (Integer i: less) if(temp.contains(i)) temp.remove(i); return temp.toArray(new Integer[temp.size()]); } private static boolean haveZero(Integer[][] newMat) { for(int i=0;i<9;i++) for(int j=0;j<9;j++) if(newMat[i][j] == 0){ return true; } return false; } public static int[] convert(Integer i) { return new int[]{i/9, i%9}; } public static int convert(Integer[] a) { return a[0]*9 + a[1]; } }
import java.util.Scanner; import java.util.ArrayList; class Point{ public int x; public int y; Point(int x, int y) { this.x = x; this.y = y; } } public class Main { public static ArrayList<Integer> FindRemain(int x, int y, int[][] input) { int[] has = new int[9]; //寻找横轴 for(int i=0;i<9;i++) { int curnum = input[y][i]; if(curnum==0) { continue; } if(has[curnum-1]==0) { has[curnum-1]=1; } } //寻找纵轴 for(int i=0;i<9;i++) { int curnum = input[i][x]; if(curnum==0) { continue; } if(has[curnum-1]==0) { has[curnum-1]=1; } } //寻找所在的3x3 int xstart = (x/3)*3; int ystart = (y/3)*3; for(int i=ystart;i<ystart+3;i++) { for(int j=xstart;j<xstart+3;j++) { int curnum = input[i][j]; if(curnum==0) { continue; } if(has[curnum-1]==0) { has[curnum-1]=1; } } } ArrayList<Integer> out = new ArrayList<>(); for(int i=0;i<has.length;i++) { if(has[i]==0) out.add(i+1); } return out; } public static ArrayList<Point> test(int[][] input) { //寻找所有的空位 ArrayList<Point> points = new ArrayList<>(); for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { if(input[i][j]==0) { Point temp = new Point(j,i); points.add(temp); } } } return points; } public static boolean isEnd = false; public static void Try(int[][] input, ArrayList<Point> list, int index) { //是否到最后一个数字了,不用isEnd进行判断则可以输出所有的可能结果 if(isEnd) { return; } if(list.size()==index) { print(input); isEnd = true; } else { Point cur = list.get(index); ArrayList<Integer> remain = FindRemain(cur.x, cur.y, input); //如果remain不为空,则代表这个位置还有几种补全的可能 for(int i=0;i<remain.size();i++) { input[cur.y][cur.x] = remain.get(i); Try(input, list, index+1); input[cur.y][cur.x] = 0; } } } public static void print(int[][] input) { for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { if(j==0) System.out.print(input[i][j]); else System.out.print(" "+input[i][j]); } if(i!=9) System.out.println(); } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNextInt()) { int[][] input = new int[9][9]; for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { input[i][j] = sc.nextInt(); } } isEnd = false; Try(input, test(input), 0); } sc.close(); } }