Leetcode | N-Queens I & II

N-Queens I

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

Leetcode | N-Queens I & II

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.."]

]

Wiki:任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

回溯,用了一个数组col[i]来表示第i列是不是已经放了queen。

对于(row1, col1)和(row2, col2)这两个位置,如果它们在同一对角线上,那么有abs(row1-row2) = abs(col1-col2)。

class Solution {

public:

    vector<vector<string> > solveNQueens(int n) {

        if (n == 2 || n == 3) {

            return ret;

        }

        vector<string> sol(n, string(n, '.'));

        vector<bool> col(n, false);

        bt(n, 0, col, sol);

        return ret;

    }

    

    void bt(int n, int r, vector<bool> &col, vector<string> &sol) {

        if (r >= n) {

            ret.push_back(sol);

            return;

        }

    

        for (int i = 0; i < n; ++i) {

            if (col[i]) continue;



            bool diag = false;

            for (int j = r - 1; j >= 0; --j) {

                for (int m = 0; m < n; ++m) {

                    if (abs(j - r) == abs(m - i) && sol[j][m] == 'Q') {

                        diag = true;

                        break;

                    }

                }

            }   

            

            if (!diag) {

                col[i] = true;

                sol[r][i] = 'Q';

                bt(n, r + 1, col, sol);

                col[i] = false;

                sol[r][i] = '.';

            }

        }

        

    }



private:

    vector<vector<string> >  ret;

};

 N-Queens II

Follow up for N-Queens problem.

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

 

和N-Queens I 类似,同样需要回溯。

前面回溯的时候需要用到一个额外的数组col[i],而且用到了sol这个数组来判断对角线元素。

网上的解决方案更巧妙些,用到一个数组sol[i],存的是第i行可解的列号。

当处理到第r行时,检查前r-1行,看sol[0...r-1]有没有等于i的,有就代表了该列已经有queen了。然后再检查对角线上的。

 1 class Solution {

 2 public:

 3     int totalNQueens(int n) {

 4         if (n == 2 || n == 3) {

 5             return 0;

 6         }

 7         vector<int> sol(n, -1);

 8         total = 0;

 9         bt(n, 0, sol);

10         return total;

11     }

12     

13     void bt(int n, int r, vector<int> &sol) {

14         if (r >= n) {

15             total++;

16             return;

17         }

18     

19         for (int i = 0; i < n; ++i) {

20             bool valid = true;

21             for (int j = r - 1; j >= 0; --j) {

22                 for (int m = 0; m < n; ++m) {

23                     if (sol[j] == i || abs(j - r) == abs(sol[j] - i)) {

24                         valid = false;

25                         break;

26                     }

27                 }

28             }   

29             

30             if (valid) {

31                 int t = sol[r];

32                 sol[r] = i;

33                 bt(n, r + 1, sol);

34                 sol[r] = t;

35             }

36         }

37         

38     }

39 

40 private:

41     int total;

42 };

 第三次写,在返回值统计。至此leetcode三遍刷完。

 1 class Solution {

 2 public:

 3     int totalNQueens(int n) {

 4         if (n <= 0) return 0;

 5         vector<int> colSetted(n, -1);

 6         return recurse(n, 0, colSetted);

 7     }

 8     

 9     int recurse(int n, int row, vector<int> &colSetted) {

10         if (row >= n) {

11             return 1;

12         }

13         

14         int count = 0;

15         for (int i = 0; i < n; ++i) {

16             if (colSetted[i] == -1) {

17                 bool couldSet = true;

18                 for (int j = 0; j < n; ++j) {

19                     if (colSetted[j] != -1 && abs(row - colSetted[j]) == abs(i - j)) {

20                         couldSet = false;

21                         break;

22                     }

23                 }

24                 if (couldSet) {

25                     colSetted[i] = row;

26                     count += recurse(n, row + 1, colSetted);

27                     colSetted[i] = -1;

28                 }

29             }

30         }

31         return count;

32     }

33 };

 

你可能感兴趣的:(LeetCode)