八皇后问题和数独问题

八皇后问题和数独问题是经典dfs+回溯的问题,其中还可以涉及hash,是非常好的练习题目。我们以leetcode中的四道题目为例。


Valid Sudoku

  Total Accepted: 40598   Total Submissions: 149092 

Determine if a Sudoku is valid

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.


A partially filled sudoku which is valid.

Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.

简单的判断数独表是否有解,只需要穷举每个元素判断其所在行、列以及小九宫格内没有和它相同的元素,为此我们可以建立hash表。

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        int showed_col[9][9]={0}, showed_row[9][9]={0}, showed_sub[9][9]={0};
        for(int i = 0 ; i < board.size();i++){
            for(int j = 0; j < board[i].size(); j++){
                int num = board[i][j] - '0' -1;
                int sub = i/3*3+j/3;
                if(board[i][j] !='.'){
                    if(showed_col[i][num] || showed_row[num][j] || showed_sub[sub][num])
                        return false;
                    showed_col[i][num] = 1;
                    showed_row[num][j] = 1;
                    showed_sub[sub][num] = 1;
                }
            }
        }
        return true;
        
    }
};

Sudoku Solver

  Total Accepted: 31158   Total Submissions: 142451


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.

求出数独的解,这里有个前提就是数独的解是唯一的,通过dfs+回溯解决。一共有两个核心函数,一个是回溯函数,一个是判断函数。

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        solve(board,0);
    }
    
      
    bool isValidFill(vector<vector<char>> &board, int i,int j, char fill) {
        for(int k = 0; k < 9; k++) {
            if(board[i][k] == fill) return false;
            if(board[k][j] == fill) return false;
            int r = i/3*3+j/3;
            if(board[r/3*3+k/3][r%3*3+k%3] == fill) return false;
        }
        return true;
    }
 
    bool solve(vector<vector<char>>&board, int ind) {
        if(ind == 81) return true;
        int i = ind/9, j = ind%9;
        if(board[i][j] !='.') return solve(board, ind+1);
        else{
            for(char f = '1'; f<='9'; f++) {
                if(isValidFill(board,i,j,f)){
                    board[i][j] = f;
                    if(solve(board,ind+1)) return true;
                    board[i][j] = '.';
                }
            }
        }
        return false;
    }
  
    
}; 

下面我们会看到,八皇后问题与数独问题的求解十分相似。

N-Queens

  Total Accepted: 34322   Total Submissions: 129991

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

For example,
There exist two distinct solutions to the 4-queens puzzle:

[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<string> nQueens(n, string(n,'.'));
        solveNQueens(res, nQueens, 0, n);
        return res;
    }

    bool isValid(vector<string> &nQueens, int row,int col,int &n){
        for(int i=0; i != row; i++) {
            if(nQueens[i][col] == 'Q')
                return false;
        }
        
        for(int i = row -1, j = col -1; i >=0 && j>=0;--i,--j){
            if(nQueens[i][j] == 'Q')
            return false;
        }
        
        for(int i = row -1, j = col+1;i>=0&&j>=0;--i,++j){
            if(nQueens[i][j] == 'Q')
                return false;
        }
        return true;
    }
    
        
    void solveNQueens(vector<vector<string>> &res,vector<string> &nQueens,int row, int &n){
        if(row == n) {
            res.push_back(nQueens);
            return;
        }
        for(int col = 0; col!=n;col++){
            if(isValid(nQueens, row, col, n)) {
                nQueens[row][col] = 'Q';
                solveNQueens(res, nQueens,row+1,n);
                nQueens[row][col] = '.';
            }
        }
    }
    

};

N-Queens II

  Total Accepted: 29382   Total Submissions: 81802


Follow up for N-Queens problem.

Now, instead outputting board configurations, return the total number of distinct solutions.

class Solution {
public:
    int totalNQueens(int n) {
        int result = 0;
        vector<int> A(n,-1);
        NQueens(n,result,0,A);
        return result;
    }
    
    bool isValid(vector<int> &A, int r){
        for(int i = 0; i < r; i++) {
            if((A[i] == A[r]) || (abs(A[i]-A[r]) == (r-i)))
                return false;
        }
        return true;
    }
    
    void NQueens(int n, int &result, int cur, vector<int> &A) {
        if(cur == n) {
            result++;
            return;
        }else{
            for(int i = 0; i < n; i++) {
                A[cur] = i;
                if(isValid(A,cur))
                    NQueens(n,result,cur+1,A);
            }
        }
    }
    
};


 


你可能感兴趣的:(八皇后问题和数独问题)