问题描述:数独(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.*; 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.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); } }
#include<stdio.h> #define N 9 #define MOD 3 int is_valid(int (*p)[N], int row, int col) { int check[N + 1] = {0}; for (int i = 0; i < N + 1; i++) check[i] = 1; for (int i = 0; i < N; i++) { if (check[p[row][i]]) check[p[row][i]] = 0; else if (p[row][i] != 0) return 0; } for (int i = 0; i < N + 1; i++) check[i] = 1; for (int i = 0; i < N; i++) { if (check[p[i][col]]) check[p[i][col]] = 0; else if (p[i][col] != 0) return 0; } for (int i = 0; i < N + 1; i++) check[i] = 1; int r0 = row - row % MOD; int c0 = col - col % MOD; for (int k = 0; k < N; k++) { int r = r0 + k / MOD; int c = c0 + k % MOD; if (check[p[r][c]]) check[p[r][c]] = 0; else if (p[r][c] != 0) return 0; } return 1; } int sudoku(int (*p)[N], int depth) { if (depth == 0) { return 0; } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (p[i][j] == 0) { for (int k = 1; k <= N + 1; k++) { if (k == N + 1) return depth; p[i][j] = k; if (is_valid(p, i, j)) { depth--; depth = sudoku(p, depth); if (depth == 0) return 0; depth++; } p[i][j] = 0; } } } } return depth; } int main() { int a[N][N] = {0}; int depth = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { scanf("%d", &a[i][j]); if (a[i][j] == 0) depth++; } } sudoku(a, depth); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf((j == N - 1) ? "%d\n" : "%d ", a[i][j]); } } return 0; }
import java.util.Arrays; import java.util.Scanner; import java.util.stream.IntStream; public class Main { private static int BOARD_SIZE = 9; private static int SUBSECTION_SIZE = 3; private static int NO_VALUE = 0; private static int MIN_VALUE = 1; private static int MAX_VALUE = 9; private static int BOARD_START_INDEX = 0; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[][] bc = new int[9][9]; while (sc.hasNextLine()) { for (int i = 0; i < 9; i++) { String str = sc.nextLine(); String[] ss = str.split(" "); for (int j = 0; j < 9; j++) { bc[i][j] = Integer.parseInt(ss[j]); } } solve(bc); printBoard(bc); } } private static boolean isValid(int[][] board, int row, int column) { return (rowConstraint(board, row) && columnConstraint(board, column) && subsectionConstraint(board, row, column)); } private static boolean rowConstraint(int[][] board, int row) { boolean[] constraint = new boolean[BOARD_SIZE]; return IntStream.range(BOARD_START_INDEX, BOARD_SIZE) .allMatch(column -> checkConstraint(board, row, constraint, column)); } private static boolean columnConstraint(int[][] board, int column) { boolean[] constraint = new boolean[BOARD_SIZE]; return IntStream.range(BOARD_START_INDEX, BOARD_SIZE) .allMatch(row -> checkConstraint(board, row, constraint, column)); } private static boolean subsectionConstraint(int[][] board, int row, int column) { boolean[] constraint = new boolean[BOARD_SIZE]; int subsectionRowStart = (row / SUBSECTION_SIZE) * SUBSECTION_SIZE; int subsectionRowEnd = subsectionRowStart + SUBSECTION_SIZE; int subsectionColumnStart = (column / SUBSECTION_SIZE) * SUBSECTION_SIZE; int subsectionColumnEnd = subsectionColumnStart + SUBSECTION_SIZE; for (int r = subsectionRowStart; r < subsectionRowEnd; r++) { for (int c = subsectionColumnStart; c < subsectionColumnEnd; c++) { if (!checkConstraint(board, r, constraint, c)) return false; } } return true; } private static boolean checkConstraint(int[][] board, int row, boolean[] constraint, int column) { if (board[row][column] != NO_VALUE) { if (!constraint[board[row][column] - 1]) { constraint[board[row][column] - 1] = true; } else { return false; } } return true; } private static void printBoard(int[][] board) { for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) { System.out.println(Arrays.toString(board[row]).replaceAll("[,\\[\\]]", "")); } } private static boolean solve(int[][] board) { for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) { for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) { if (board[row][column] == NO_VALUE) { for (int k = MIN_VALUE; k <= MAX_VALUE; k++) { board[row][column] = k; if (isValid(board, row, column) && solve(board)) { return true; } board[row][column] = NO_VALUE; } return false; } } } return true; } }case通过率为83.33%
代码如下: #include <iostream> using namespace std; bool sign = false; int num[9][9]; void Output() { for (int i = 0; i < 9; i++){ for (int j = 0; j < 8; j++) cout << num[i][j] << " "; cout << num[i][8]; cout << endl; } } /* 判断key填入n格时是否满足条件,n代表第几个格子 */ bool Check(int n, int key) { /* 判断n所在横列是否合法 */ for (int i = 0; i < 9; i++){ /* j为n竖坐标 */ int j = n / 9; if (num[j][i] == key) return false; } /* 判断n所在竖列是否合法 */ for (int i = 0; i < 9; i++){ /* j为n横坐标 */ int j = n % 9; if (num[i][j] == key) return false; } int y = n / 9 / 3 * 3; int x = n % 9 / 3 * 3; /* 判断n所在的小九宫格是否合法 */ for (int i = y; i < y + 3; i++) for (int j = x; j < x + 3; j++) if (num[i][j] == key) return false; return true; } /* 深搜 */ int DFS(int n) { /* 所有的都符合,退出搜索,n代表格子数,共81个格子,0~80 */ if (n > 80){ sign = true; return 0; } if (num[n / 9][n % 9] != 0) DFS(n + 1); else{ /* 否则对当前位一次填入1~9进行测试 */ for (int i = 1; i <= 9; i++){ if (Check(n, i)){ num[n / 9][n % 9] = i; /* 继续搜索,后续位也填1~9测试,直到最后一位,通过的话置true */ DFS(n + 1); /* 返回时如果构造成功,则直接退出 */ if (sign) return 0; /* 如果构造不成功,还原当前位 */ num[n/9][n%9] = 0; } } } return 0; } int main() { for (int i = 0; i < 9; i++){ for (int j = 0; j < 9; j++) cin >> num[i][j]; } DFS(0); //从第0格开始填 Output(); }
#-*- coding: utf8 -*- def check(matrix,row,col,value): """ 检测在(row,col)放value是否合适 1.每行含1-9,不含重复值value 2.每列含1-9,不含重复值value 3.3*3区块含1-9,不含重复值value """ #检测每行 for j in range(9): if matrix[row][j]==value: return False #检测每列 for i in range(9): if matrix[i][col]==value: return False #检测元素所在3*3区域 area_row=(row/3)*3 area_col=(col/3)*3 for i in range(area_row,area_row+3): for j in range(area_col,area_col+3): if matrix[i][j]==value: return False return True def solveSudoku(matrix,count=0): """ 遍历每一个未填元素,遍历1-9替换为合适的数字 """ if (count==81):#递归出口 return True row=count/9#行标 col=count%9#列标 if (matrix[row][col]!=0):#已填充 return solveSudoku(matrix,count=count+1) else:#未填充 for i in range(1,10): if check(matrix,row,col,i):#找到可能的填充数 matrix[row][col]=i if solveSudoku(matrix,count=count+1):#是否可完成 return True#可完成 #不可完成 matrix[row][col]=0#回溯 return False#不可完成 matrix=[] for i in range(9): matrix.append(map(int,raw_input().split(' '))) solveSudoku(matrix) for i in range(9): print ' '.join(map(str,matrix[i]))
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[][] matrix = new int[9][9]; while (sc.hasNext()) { for (int i = 0; i < 9; i ++) { for (int j = 0; j < 9; j ++) { matrix[i][j] = sc.nextInt(); } } sudoku(matrix, 0, 0); for (int i = 0; i < 9; i ++) { for (int j = 0; j < 9; j ++) { if(j == 8) System.out.println(matrix[i][j]); else System.out.print(matrix[i][j] + " "); } } } } public static boolean sudoku(int[][] matrix, int i, int j) { if(i > 8) return true; if(matrix[i][j] != 0) { if(j < 8 && sudoku(matrix, i, j + 1)) return true; // 未到行位,求解同行下一个 else if(j >= 8 && sudoku(matrix, i + 1, 0)) return true; // 已到行位,求解下一行第一个 } else { for (int num = 1; num <= 9; num ++) { if(check(matrix, i, j, num)) { matrix[i][j] = num; if(j < 8 && sudoku(matrix, i, j + 1)) return true; else if(j >= 8 && sudoku(matrix, i + 1, 0)) return true; matrix[i][j] = 0; // 回溯 } } } return false; } // 检查行、列、3*3格 public static boolean check(int[][] matrix, int i, int j, int num) { if(check_row(matrix, i, j, num) && check_col(matrix, i, j, num) && check_3_by_3(matrix, i, j, num)) return true; return false; } // 检查所在行 public static boolean check_row(int[][] matrix, int i, int j, int num) { for (int k = 0; k < 9; k ++) { if(matrix[i][k] == num) return false; } return true; } // 检查所在列 public static boolean check_col(int[][] matrix, int i, int j, int num) { for (int k = 0; k < 9; k ++) { if(matrix[k][j] == num) return false; } return true; } // 检查所在3*3格 public static boolean check_3_by_3(int[][] matrix, int i, int j, int num) { int row_from = i / 3 * 3; int row_to = row_from + 2; int col_from = j / 3 * 3; int col_to = col_from + 2; for (int x = row_from; x <= row_to; x ++) { for (int y = col_from; y <= col_to; y ++) { if(matrix[x][y] == num) return false; } } return true; } }
def value(x, y): i, j = x // 3, y // 3 grid = [m[i * 3 + r][j * 3 + c] for r in range(3) for c in range(3)] row_val = m[x] col_val = list(zip(*m))[y] return {1, 2, 3, 4, 5, 6, 7, 8, 9} - set(grid) - set(row_val) - set(col_val) def sudoku(pos): if not pos: # 填完了 res.append([' '.join(map(str, i)) for i in m]) else: x, y = pos[0] val = value(x, y) if val: for v in val: m[x][y] = v sudoku(pos[1:]) m[x][y] = 0 # 回溯 m = [list(map(int, input().split())) for i in range(9)] pos = [(x, y) for y in range(9) for x in range(9) if not m[x][y]] res = [] sudoku(pos) print('\n'.join(res[0]))
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.*; public class Main { public static void main(String[] args) { int[][] board = new int[9][9]; Scanner in = new Scanner(System.in); for (int i = 0; i < board[0].length; i++) for (int j = 0; j < board.length; j++) board[i][j] = in.nextInt(); in.close(); solveSudoku(board); for (int i = 0; i < board[0].length; i++) { for (int j = 0; j < board.length - 1; j++) System.out.print(board[i][j] + " "); System.out.println(board[i][board.length - 1]); } } static int solveSudoku(int[][] board) { int depth = 0; for (int i[] : board) for (int j : i) if (j == 0) depth++; return dfs(board, depth); } static int dfs(int[][] board, int depth) { if (depth == 0) return 0; for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (board[i][j] == 0) { for (int k = 1; k <= 10; k++) { if (k == 10) return depth; board[i][j] = k; if (!isValid(board, i, j)) board[i][j] = 0; else { depth--; depth = dfs(board, depth); if (depth == 0) return depth; depth++; board[i][j] = 0; } } } } } return depth; } static boolean isValid(int[][] board, int row, int col) { boolean[] check = new boolean[10]; for (int i = 0; i < check.length; i++) check[i] = true; for (int i = 0; i < board[0].length; i++) { if (check[board[row][i]]) check[board[row][i]] = false; else if (board[row][i] != 0) return false; } for (int i = 0; i < check.length; i++) check[i] = true; for (int i = 0; i < board.length; i++) { if (check[board[i][col]]) check[board[i][col]] = false; else if (board[i][col] != 0) return false; } for (int i = 0; i < check.length; i++) check[i] = true; int rowTemp = (row / 3) * 3; int colTemp = (col / 3) * 3; for (int k = 0; k < 9; k++) { row = rowTemp + k / 3; col = colTemp + k % 3; if (check[board[row][col]]) check[board[row][col]] = false; else if (board[row][col] != 0) 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; } } } }
#include <iostream> #include<vector> using namespace std; class Sudoku{ private: vector<vector<int>> sudoku; public: Sudoku() { sudoku.resize(9, vector<int>(9)); for(int i = 0; i < 9; ++i) { for(int j = 0; j < 9; ++j) cin >> sudoku[i][j]; } }; bool sudokuCheck(int i, int j, int n) { for(int p = 0; p < 9; ++p) { if (this->sudoku[i][p] == n) return false; if (this->sudoku[p][j] == n) return false; } int ii = (int)(i / 3) * 3; int jj = (int)(j / 3) * 3; for(int p = 0; p < 3; ++p) { for(int q = 0; q < 3; ++q) { if (this->sudoku[ii + p][jj + q] == n) return false; } } return true; } bool sudokuCkeckDFS() { for(int i = 0; i < 9; ++i) { for(int j = 0; j < 9; ++j) { if(this->sudoku[i][j] == 0) return false; } } return true; } void sudokuDFS(int i, int j) { if(j >= 9) { j-=9; i++; } if(i >= 9) return; if(this->sudoku[i][j] != 0) { sudokuDFS(i, j + 1); } else{ for(int num = 1; num <= 9; ++num) { if(sudokuCheck(i, j, num)) { this->sudoku[i][j] = num; sudokuDFS(i, j + 1); if(sudokuCkeckDFS()) return; this->sudoku[i][j] = 0; } } } } void sudokuPrint() { for(int i = 0; i < 9; ++i) { for(int j = 0; j < 9; ++j) cout<<sudoku[i][j] <<" "; cout << endl; } } }; int main() { Sudoku sudoku; sudoku.sudokuDFS(0, 0); sudoku.sudokuPrint(); return 0; }
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; } }
// 回溯,验证数的合法性的地方想了一下( // 思路大概就是如下 #include <iostream> #include <vector> using namespace std; bool isValid(vector<vector<int>>& arr, int i, int j, int num) { for (int k = 0; k < 9; k++) { if (arr[k][j] == num) // 列中重复 return false; if (arr[i][k] == num) // 行中重复 return false; if (arr[(i / 3) * 3 + k / 3][(j / 3) * 3 + k % 3] == num) //3*3方格内是否有重复 return false; } return true; } // 返回bool值,一找到可行解就return,省时间 bool backtrack(vector<vector<int>>& arr, int i, int j) { if (i == 9) // base case,碰到直接返回 return true; if (j == 9) // 这一行穷举完了就换下一行 return backtrack(arr, i + 1, 0); if (arr[i][j] != 0) // 这格已经有数字了的话就跳过 return backtrack(arr, i, j + 1); // 对每个格子,可以选择1~9 for (int k = 1; k <= 9; k++) { // 先判断当前的数字能否放到格子里, 剪枝 if (!isValid(arr, i, j, k)) continue; // 做选择 arr[i][j] = k; // 继续穷举右边一个 if (backtrack(arr, i, j + 1)) return true; //撤销选择 arr[i][j] = 0; } return false; } int main() { vector<vector<int>> arr(9, vector(9, 0)); for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) cin >> arr[i][j]; backtrack(arr, 0, 0); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) cout << arr[i][j] << " "; cout << endl; } }
a = [] def check(row, col, v):#传入位置和这个元素 for k in range(9):#判断,如果在这一行或者这一列里面以及有元素等于v了,就返回false if a[row][k] == v&nbs***bsp;a[k][col] == v: return False t = row//3#把9×9的转变为9个3×三的小矩阵 q = col//3 for k in range(t*3,t*3+3):#判断这个小矩阵,看这个小矩阵里面是否有元素等于这个数,如果有,就返回false!为什么判断这个呢??哦,题目要求了,这个小的矩形也不能重复的 for p in range(q*3,q*3+3): if a[k][p] == v: return False return True def f(num):#不断的判断,某个位置是否能够填这个数。 global a if num > 80: return True#大于80,说明全部扫完了。 row = num // 9#行数,行数和列数是变化的。明显列数变化的比行快一些 col = num % 9#列数 if a[row][col] != 0: return f(num+1)#不等于0,说明这个地方有数,占住了位子 else:#否则,就是等于0,需要考虑填什么数合适 for i in range(1,10): if check(row,col,i): #检查,这个位置填i可以吗,如果可以则填 a[row][col] = i if f(num+1): return True else: a[row][col] = 0 return False while True: try: for i in range(9): b = list(map(int,input().split())) a.append(b) f(0) for i in range(9): print(' '.join(map(str,a[i]))) except: break批注了一下,便于理解这一段代码,排第一的python解法
#include <iostream> using namespace std; int flag = 0; int a[9][9]; //思想 //遍历矩阵,判断数字是否为0 //若为0,判断1-9哪个数字合适(因此需要判断,0所在行,所在列,所在9宫格是否有重复) //若没有重复,则复制,继续循环到第81个数字,那么说明数独填数成功 bool isok(int n,int k) { int x = n/9; int y = n%9; for(int i=0;i<9;i++) { if(a[x][i] == k) return false; } for(int i=0;i<9;i++) { if(a[i][y] == k) return false; } x = x/3 *3; y = y/3 *3; for(int i = x;i<x+3;i++) { for(int j = y;j<y+3;j++) { if(a[i][y] == k) return false; } } return true; } void dfs(int n) { if(n > 80) { flag =1; return ; } int x = n/9; int y = n%9; if(a[x][y] != 0) { dfs(n+1); } else { for(int i = 1;i<=9;i++) { if(isok(n,i)) { a[x][y] = i; dfs(n+1); if(flag == 1) return; else a[x][y] = 0; } } } } int main() { for(int i = 0;i<9;i++) for(int j = 0;j<9;j++) cin>>a[i][j]; dfs(0); for(int i = 0;i<9;i++) { for(int j = 0;j<9;j++) { cout<<a[i][j]<<" "; } cout<<endl; } return 0; }
def check(sod,loc,value): x, y = loc//9,loc%9 row = sod[x] column = list(b[y] for b in sod) x1,y1 = (x//3)*3,(y//3)*3 L1,L2,L3 = sod[x1][y1:y1+3],sod[x1+1][y1:y1+3],sod[x1+2][y1:y1+3] matrix = L1+L2+L3 allnum = row+column+matrix+[0] if value in allnum: return False else: return True def solver(sodoku:list): total = [] def search(sodo:list,nowloc=0): if nowloc == 81: for i in sodo: print(' '.join(list(map(str,i)))) return True x, y = nowloc//9,nowloc%9 if sodo[x][y] == 0: for i in range(1,10,1): if check(sodo,nowloc,i): sodo[x][y] = i if search(sodo,nowloc+1): return True else: sodo[x][y] = 0 return False else: search(sodo,nowloc+1) return False search(sodoku,0) return total for i in range(1): try: mylist = [] for i in range(9): mylist.append(list(map(int,input().split()))) solver(mylist) except: break题目不完整,缺少粗线框的限制
import java.util.*; class Test { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int[][] arr = new int[9][9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { arr[i][j] = scanner.nextInt(); } } if(!find(arr))System.out.println("no solution"); else { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { System.out.print(arr[i][j]+" "); } System.out.println(); } } } scanner.close(); } public static boolean find(int[][] arr) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if(arr[i][j]==0){ for (int j2 = 0; j2 < 10; j2++) { if(ok(arr,i,j,j2)) return true; } return false; } } } return true; } public static boolean ok(int[][] arr,int a,int b,int num){ for (int i = 0; i < 9; i++) { if(arr[a][i]==num)return false; } for (int i = 0; i < 9; i++) { if(arr[i][b]==num)return false; } for (int i = a/3*3; i < a/3*3+3; i++) { for (int j = b/3*3; j < b/3*3+3; j++) { if(arr[i][j]==num)return false; } } arr[a][b]=num; if(!find(arr)){ arr[a][b]=0; return false; } return true; } }AC代码