• Sudoku Solver


    Write a program to solve a Sudoku puzzle by filling the empty cells.

    Empty cells are indicated by the character '.'.

    You may assume that there will be only one unique solution.

    A sudoku puzzle...

    ...and its solution numbers marked in red.

    做了这道题,对backtracking的理解又加深了一点点。

    1 每个backtracking的题目,最好都有独立判断isValid的程序,这样架构清楚。同时,valid判断函数在这里可以稍微研究一下。只要当前要判断的位置上的数值和本行没有重复,本列没有重复,九宫格没有重复就可以。一旦重复立即返回,减少判断次数。

    2 backtracking的递归函数,怎么能没有返回值呢?!因为要判断递归的方案正确与否,所以这里的递归一定是有返回值的(除非是combination那种没有正确错误概念的backtracking)!

    3 可以考虑“先放置,再判断”的方案。比如这里,首先判断当前位置是否为空,如果为空,那么放置一个元素,检查它是否正确。如果正确,就继续进行下面的递归(也就是第29行 isValid&&solveSudoku的作用)。当函数返回错误之后,将刚刚的数值变为空,再进行下一次尝试即可。

    4 所有的方案(k从1到9)完毕之后,应该返回错误,这个是不应该被忽略的。

    5 最后一点需要注意的是,当i,j循环完毕之后,第36行应该返回true。这里实际上是最终/最底层的一次循环,表明已经解出了sudoku,返回true!切记切记,最终情况!

     1 public class Solution {
     2     public boolean solveSudoku(char[][] board) {
     3         // Note: The Solution object is instantiated only once and is reused by each test case.
     4         for (int i = 0; i < 9; i ++){
     5             for (int j = 0; j < 9; j ++)
     6             {
     7                 if (board[i][j] == '.')
     8                 {
     9                     for (int k = 1; k <= 9; k ++)
    10                     {
    11                         board[i][j] = (char)(k + '0');
    12                         if (isValid(board, i, j) && solveSudoku(board)){
    13                             return true;
    14                         }
    15                         board[i][j] = '.';
    16                     }
    17                     return false;  
    18                 }
    19             }
    20         }
    21         return true;
    22     }
    23     public boolean isValid(char[][] board, int x, int y){
    24         int i = 0;
    25         int j = 0;
    26         for (; i < 9; i++)
    27             if (i != x && board[i][y] == board[x][y])
    28                 return false;
    29         for (; j < 9; j++)
    30             if (j != y && board[x][j] == board[x][y])
    31                 return false;
    32         for (i = 3 * (x / 3); i < 3 * (x / 3 + 1); i++)
    33             for (j = 3 * (y / 3); j < 3 * (y / 3 + 1); j++)
    34                 if (i != x && j != y && board[i][j] == board[x][y])
    35                     return false;
    36         return true;
    37     }
    38 }

     第三遍:

     1 public class Solution {
     2     public boolean solveSudoku(char[][] board) {
     3         for(int i = 0; i < 9; i ++)
     4             for(int j = 0; j < 9; j ++)
     5                 if(board[i][j] == '.'){
     6                     for(int k = 1; k < 9; i ++){
     7                         board[i][j] = (char)(k + '0');
     8                         if(isValid(board, i , j) && solveSudoku(board)) return true;
     9                         board[i][j] = '.';
    10                     }
    11                     return false;
    12                 }
    13         return true;
    14     }
    15     
    16     public boolean isValid(char[][] board, int a, int b){
    17         for(int i = 0; i < 9; i ++){
    18             if(i != a && board[a][b] == board[i][b]) return false;
    19             if(i != b && board[a][b] == board[a][i]) return false;
    20         }
    21         for(int i = 3 * (a / 3); i < 3 * (a / 3) + 3; i ++)
    22             for(int j = 3 * (b / 3); j < 3 * (b / 3) + 3; i ++)
    23                 if(i != a && j != b && board[i][j] == board[a][b]) return false;
    24         return true;
    25     }
    26 }
  • 相关阅读:
    CH1301 邻值查找【set应用】
    poj1185 炮兵阵地【状压DP】
    codeforces#516 Div2---ABCD
    2017ACM-ICPC沈阳区域赛
    poj2411 Mondriaan's Dream【状压DP】
    hdu2196 Computer【树形DP】【换根法】
    poj3345 Bribing FIPA【树形DP】【背包】
    poj1463 Strategic game【树形DP】
    poj1191 棋盘分割【区间DP】【记忆化搜索】
    CH5E09 能量相连【区间DP】
  • 原文地址:https://www.cnblogs.com/reynold-lei/p/3366321.html
Copyright © 2020-2023  润新知