51. N-Queens
问题:
给一个 N×N 的棋盘,可放置 N 个皇后,使得它们不能互相攻击。
PS:皇后可以攻击同一行、同一列、左上左下右上右下四个方向的任意单位。
Example 1: Input: n = 4 Output: [[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above Example 2: Input: n = 1 Output: [["Q"]] Constraints: 1 <= n <= 9
解法:Backtracking(回溯算法)DFS(深度优先搜索 Depth-First-Search)
变量:
- 路径:到当前行为止,上面的行所确定的Q位置。
- 选择:对当前行,可选择任意一列(满足不与上方确定的Q冲突)。
处理:
- base:处理到最后一行,则将路径加入res,退出递归
- 决定选择:若当前行的该列满足条件(不与上方Q冲突),则将该位置加入path路径。将该位置只为"Q"。
- 撤销选择:将该位置只为空"."。
⚠️ 注意:这里对满足条件(不与上方Q冲突),提出一个函数isValid进行判断处理
分别判断已经确定好的path中,该位置[row, col]的上方↑左上方↖︎右上方↗︎,都没有Q,则返回true。
代码参考:
1 class Solution { 2 public: 3 bool isValid(vector<string> path, int row, int col) { 4 int n = path.size(); 5 //check if there is a Queen already in the same col above.↑ 6 for(int i = 0; i < row; i++) { 7 if(path[i][col]=='Q') return false; 8 } 9 //check if there is a Queen already in its left up.↖︎ 10 for(int i = row-1, j = col-1; i >= 0 && j >= 0; i--, j--) { 11 if(path[i][j]=='Q') return false; 12 } 13 //check if there is a Queen already in its right up.↗︎ 14 for(int i = row-1, j = col+1; i >= 0 && j < n; i--, j++) { 15 if(path[i][j]=='Q') return false; 16 } 17 return true; 18 } 19 void traverse(vector<string> path, int row) {//for each row 20 if(row == path.size()) { 21 res.push_back(path); 22 return; 23 } 24 int n = path.size(); 25 for(int col = 0; col < n; col++) {//options: which col to choose 26 if(isValid(path, row, col)) { 27 path[row][col] = 'Q'; 28 traverse(path, row+1); 29 path[row][col] = '.'; 30 } 31 } 32 return; 33 } 34 vector<vector<string>> solveNQueens(int n) { 35 vector<string> path(n, string(n,'.')); 36 traverse(path, 0); 37 return res; 38 } 39 private: 40 vector<vector<string>> res; 41 };