1. 程式人生 > >37.sudoku-solver

37.sudoku-solver

     這道題是數獨遊戲,規則我們很清楚,小時候一般小孩都玩過,所以,題目大體意思比較好懂。

     題目大意:給定一個9*9的二位陣列,與數字和"."組成,按照數獨遊戲規則,在"."處填入數字,使得整個矩陣的每一行都是由1~9組成且沒有重複,每一列由1~9組成且沒有重複,9*9的矩陣可以分成9個3*3的二位小矩陣,而9個3*3的矩陣中,每個都是由1~9這9個數字組成,且沒有重複。

      題目要求只寫出一種可行的情況即可,那就只要有一種滿足條件,就可以返回相應的值,而在數獨遊戲過程中,後續操作要依賴於前面步驟,所以,是典型的dfs思想題目。基本思想是遇到空白位置,從1~9依次嘗試,每嘗試一次要判斷陣列是否符合要求,如果符合要求,就向下一位置探索,如果不符合要求,就換下一個數字,如果都不符合,就向前回溯,直到所有空白都被填充。

以下是AC的程式碼,思想相對比較簡單,適合新手閱讀:

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        solveSudoku1(board);
    }
    
private:
     bool solveSudoku1(vector<vector<char>>& board) {
        for (int i=0; i<board.size(); ++i) {
            for (int j=0; j<board[0].size(); ++j) {
                if (board[i][j] == '.') {
                    for (int k=0; k<9; ++k) {
                        board[i][j] = k+'1';
                        if (isvalidSudoku(board, i, j)) {
                            if (solveSudoku1(board)) {
                                return 1;
                            }
                        }
                        board[i][j] = '.';
                    }
                    return 0;
                }
            }
        }
        return 1;
    }
    
    bool isvalidSudoku(vector<vector<char>>& board, int row, int col) {
        for (int i=0; i<9; ++i) {
            if (i!=row && board[i][col]==board[row][col]) {
                return 0;
            }
        }
        
        for (int j=0; j<9; ++j) {
            if (j!=col && board[row][j]==board[row][col]) {
                return 0;
            }
        }
        
        int rstart = (row/3)*3, cstart = (col/3)*3;
        for (int i=0; i<3; ++i) {
            for (int j=0; j<3; ++j) {
                if (rstart+i != row && cstart+j != col && board[rstart+i][cstart+j]==board[row][col]) {
                    return 0;
                }
            }
        }
        return 1;
    }
};