zoukankan      html  css  js  c++  java
  • [LeetCode] 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.

    Hide Tags
     Backtracking Hash Table
     
        这题是解数独,这个嘛,我用的是递归写法,简单描述就是填写当前空格,递归下一格,遇到不行返回,不过逻辑写的不好,很多奇奇怪怪的细节的判断。
     
    算法逻辑:
    1. 创建一个辅助函数,help(vector<vector<char> > & board,int i,int ii,int j,int jj),其中i为第几行,j 第几列,ii 小框中的第几行,jj 小框中第几列。
    2. help 函数4层for 循环遍历整个9*9 矩阵,说是4层,跟两次for 是一样的,i 和j 的步长是3,for(;i<9;i+=3),因为这4个变量的初始化在函数传入的时候,所以在其循环结束时候尾部赋0,其中一个不好的地方。
    3. 4层循环内部,首先判断当前格board[i+ii][j+jj]是否为数字,不然继续循环。
    4. 创建标记finish = false,标记接下来的填入(当前格为空)能否完成整个矩阵,用于控制跳出填写,和如果填写失败修复当前格为'.' 回溯。
    5. 遍历1-9 尝试填写,需要用到bool canIn=true,判断行,列,框中的情况,如果通过判断则修改当框为遍历的数字,递归下一格,输入当前格的i ii j jj,便可以,这是第二个不好的地方,判断没有写为外部函数,另外函数的参数设置导致了很多细节问题。
    6. 下层返回的值赋予 finish ,如果为false ,表示当前填写不行,继续遍历,如果为true,跳出填写的遍历。
    7. 结束遍历后判断是否已经填写整个矩阵,如果finish 为false,表示失败了,则当前格,然后返回false,成功先别返回。
    8. 外部4层循环结束返回true。

       所以在外层循环后返回true,是假如例子上的情况,最后一个格不为空,那么按上面逻辑是不会进入内部的,而如果能够全部遍历完整个矩阵,那么表示没有在内部返回,等价于成功填写了。

        之所以使用 ii jj,是为了可以方便处理3*3框,在能否填写的时候,需要注意跳过自身与自身判断,先判断行列,然后框的时候变可以跳过当前框所在的行列了。

     1 #include <vector>
     2 #include <iostream>
     3 #include <iterator>
     4 using namespace std;
     5 
     6 class Solution {
     7 public:
     8     void solveSudoku(vector<vector<char> > &board) {
     9         help(board,0,0,0,0);
    10     }
    11     bool help(vector<vector<char> > & board,int i,int ii,int j,int jj){
    12         for(;i<9;i+=3){
    13             for(;ii<3;ii++){
    14                 for(;j<9;j+=3){
    15                     for(;jj<3;jj++){
    16                         if(board[i+ii][j+jj]!='.')  continue;
    17                         bool finish = false;
    18                         for(char c='1';c<='9'&&!finish;c++){
    19                             bool canIn= true;
    20                             for(int k=0;k<9&&canIn;k++){
    21                                 if(k!=i+ii&&board[k][j+jj]==c) canIn = false;
    22                                 if(k!=j+jj&&board[i+ii][k]==c) canIn = false;
    23                             }
    24                             for(int ti=0;ti<3&&canIn;ti++){
    25                                 if(ti == ii)   continue;
    26                                 for(int tj=0;tj<3&&canIn;tj++){
    27                                     if(tj==jj)    continue;
    28                                     if(board[ti+i][tj+j]==c)    canIn = false;
    29                                 }
    30                             }
    31                             if(canIn==false)    continue;
    32                             board[i+ii][j+jj] = c;
    33                             finish = help(board,i,ii,j,jj);
    34                         }
    35                         if(!finish){ board[i+ii][j+jj] = '.';   return false;   }
    36                     }
    37                     jj = 0;
    38                 }
    39                 j=0;
    40             }
    41             ii=0;
    42         }
    43         return true;
    44     }
    45 };
    46 
    47 int main()
    48 {
    49     vector<char> line;
    50     vector<vector<char> > board;
    51     line = {'5','3','.','.','7','.','.','.','.'};
    52     board.push_back(line);
    53     line.clear();
    54     line = {'6','.','.','1','9','5','.','.','.'};
    55     board.push_back(line);
    56     line.clear();
    57     line = {'.','9','8','.','.','.','.','6','.'};
    58     board.push_back(line);
    59     line.clear();
    60     line = {'8','.','.','.','6','.','.','.','3'};
    61     board.push_back(line);
    62     line.clear();
    63     line = {'4','.','.','8','.','3','.','.','1'};
    64     board.push_back(line);
    65     line.clear();
    66     line = {'7','.','.','.','2','.','.','.','6'};
    67     board.push_back(line);
    68     line.clear();
    69     line = {'.','6','.','.','.','.','2','8','.'};
    70     board.push_back(line);
    71     line.clear();
    72     line = {'.','.','.','4','1','9','.','.','5'};
    73     board.push_back(line);
    74     line.clear();
    75     line = {'.','.','.','.','8','.','.','7','9'};
    76     board.push_back(line);
    77     Solution sol;
    78     sol.solveSudoku(board);
    79     for(int i=0;i<board.size();i++){
    80         copy(board[i].begin(),board[i].end(),ostream_iterator<char>(cout," "));
    81         cout<<endl;
    82     }
    83     return 0;
    84 }
    View Code
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    js实现打字机效果(完整实例)
    纯css高斯背景模糊(毛玻璃,伪元素,完整实例)
    vue首次缓存判断
    vue使用bus.js在兄弟组件传值
    叶子节点和tensor的requires_grad参数
    Mysql 8.x初次安装过程中遇到MySQL 服务无法启动的解决方法
    Apriori算法介绍(Python实现)
    springBoot单参数校验全局异常抛出
    解决vue 动态添加标签给标签添加自定义方法显示not function问题
    macbook pro、gitlab、SourceTree提交代码
  • 原文地址:https://www.cnblogs.com/Azhu/p/4141820.html
Copyright © 2011-2022 走看看