N皇后问题
经典做法
| #include <string> |
| #include <iostream> |
| #include <vector> |
| #include <unordered_set> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| vector<vector<string>> res; |
| |
| unordered_set<int> columns; |
| unordered_set<int> diagonals1; |
| unordered_set<int> diagonals2; |
| |
| vector<vector<string>> solveNQueens(int n) { |
| |
| vector<int> queens(n, -1); |
| backtrack(queens, n, 0); |
| return res; |
| } |
| |
| void backtrack(vector<int> &queens, int n, int row) { |
| if (row == n) { |
| |
| vector<string> board = generateBoard(queens, n); |
| res.push_back(board); |
| return; |
| } |
| |
| for (int i = 0; i < n; i++) { |
| |
| if (columns.find(i) != columns.end()) continue; |
| |
| int d1 = row - i; |
| if (diagonals1.find(d1) != diagonals1.end()) continue; |
| |
| int d2 = row + i; |
| if (diagonals2.find(d2) != diagonals2.end()) continue; |
| |
| |
| queens[row] = i; |
| |
| columns.insert(i); |
| diagonals1.insert(d1); |
| diagonals2.insert(d2); |
| |
| backtrack(queens, n, row + 1); |
| |
| queens[row] = -1; |
| columns.erase(i); |
| diagonals1.erase(d1); |
| diagonals2.erase(d2); |
| } |
| } |
| |
| vector<string> generateBoard(vector<int> &queens, int n) { |
| vector<string> board; |
| for (int i = 0; i < n; i++) { |
| string row = string(n, '.'); |
| row[queens[i]] = 'Q'; |
| board.push_back(row); |
| } |
| return board; |
| } |
| }; |
位运算
| #include <string> |
| #include <vector> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| vector<vector<string>> res; |
| |
| |
| vector<int> queens; |
| int limit; |
| |
| vector<vector<string>> solveNQueens(int n) { |
| |
| limit = (1 << n) - 1; |
| |
| queens.resize(n, -1); |
| backtrack(n, 0, 0, 0, 0); |
| return res; |
| } |
| |
| void backtrack(int n, int row, int columns, int diagonals1, int diagonals2) { |
| if (columns == limit) { |
| |
| res.emplace_back(generateBoard(n)); |
| return; |
| } |
| |
| int ban = columns | diagonals1 | diagonals2; |
| |
| int candidate = limit & (~ban); |
| |
| while (candidate != 0) { |
| |
| int place = candidate & (-candidate); |
| queens[row] = place; |
| |
| backtrack(n, row + 1, columns | place, (diagonals1 | place) >> 1, (diagonals2 | place) << 1); |
| |
| candidate ^= place; |
| } |
| } |
| |
| vector<string> generateBoard(int n) { |
| vector<string> board; |
| for (int i = 0; i < n; i++) { |
| string str; |
| for (int j = 0; j < n; ++j) { |
| if ((queens[i] & (1 << j)) != 0) { |
| str += 'Q'; |
| } else { |
| str += '.'; |
| } |
| } |
| board.emplace_back(str); |
| } |
| return board; |
| } |
| }; |
经典做法
-
常数时间慢
-
过程
- 用数组记录每一行的皇后所在列
- 到 row 行时,根据之前行上的皇后位置,判断能放在哪些列
- 把所有能放的列都尝试一边,每次尝试修改路径数组表示当前的决策
- 用 set 标记列和斜线上是否已经存在皇后
| #include <string> |
| #include <iostream> |
| #include <vector> |
| #include <unordered_set> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| |
| unordered_set<int> columns; |
| unordered_set<int> diagonals1; |
| unordered_set<int> diagonals2; |
| |
| vector<int> queens; |
| int res; |
| |
| void backtrack(int n, int row) { |
| if (row == n) { |
| res++; |
| return; |
| } |
| for (int i = 0; i < n; ++i) { |
| |
| if (columns.find(i) != columns.end()) continue; |
| int d1 = i - row; |
| if (diagonals1.find(d1) != diagonals1.end()) continue; |
| int d2 = i + row; |
| if (diagonals2.find(d2) != diagonals2.end()) continue; |
| |
| queens[row] = i; |
| |
| columns.emplace(i); |
| diagonals1.emplace(d1); |
| diagonals2.emplace(d2); |
| |
| backtrack(n, row + 1); |
| |
| queens[row] = -1; |
| columns.erase(i); |
| diagonals1.erase(d1); |
| diagonals2.erase(d2); |
| } |
| |
| } |
| |
| int totalNQueens(int n) { |
| res = 0; |
| |
| queens.resize(n, -1); |
| backtrack(n, 0); |
| return res; |
| } |
| }; |
- 遍历之前的皇后,检查和当前位置是否冲突
| #include <string> |
| #include <iostream> |
| #include <vector> |
| #include <unordered_set> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| |
| vector<int> queens; |
| int res; |
| |
| void backtrack(int n, int row) { |
| if (row == n) { |
| res++; |
| return; |
| } |
| for (int column = 0; column < n; ++column) { |
| if (!isValid(row, column)) continue; |
| queens[row] = column; |
| |
| backtrack(n, row + 1); |
| |
| } |
| } |
| |
| |
| bool isValid(int row, int column) { |
| for (int i = 0; i < row; ++i) |
| if (column == queens[i] || abs(row - i) == abs(column - queens[i])) |
| return false; |
| return true; |
| } |
| |
| int totalNQueens(int n) { |
| res = 0; |
| |
| queens.resize(n, -1); |
| backtrack(n, 0); |
| return res; |
| } |
| }; |
- 递归带返回值
| #include <string> |
| #include <iostream> |
| #include <vector> |
| #include <unordered_set> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| |
| vector<int> queens; |
| |
| |
| int backtrack(int n, int row) { |
| if (row == n) return 1; |
| int res = 0; |
| for (int column = 0; column < n; ++column) { |
| if (!isValid(row, column)) continue; |
| queens[row] = column; |
| |
| res += backtrack(n, row + 1); |
| } |
| return res; |
| } |
| |
| |
| bool isValid(int row, int column) { |
| for (int i = 0; i < row; ++i) |
| if (column == queens[i] || abs(row - i) == abs(column - queens[i])) |
| return false; |
| return true; |
| } |
| |
| int totalNQueens(int n) { |
| queens.resize(n, -1); |
| return backtrack(n, 0); |
| } |
| }; |
位运算
| using namespace std; |
| |
| class Solution { |
| public: |
| int res; |
| int limit; |
| |
| |
| |
| void backtrack(int columns, int diagonals1, int diagonals2) { |
| if (columns == limit) { |
| |
| res++; |
| return; |
| } |
| |
| |
| int ban = columns | diagonals1 | diagonals2; |
| |
| int candidate = limit & (~ban); |
| |
| while (candidate != 0) { |
| |
| int place = candidate & (-candidate); |
| |
| backtrack(columns | place, (diagonals1 | place) >> 1, (diagonals2 | place) << 1); |
| |
| candidate ^= place; |
| } |
| } |
| |
| int totalNQueens(int n) { |
| res = 0; |
| |
| limit = (1 << n) - 1; |
| backtrack(0, 0, 0); |
| return res; |
| } |
| }; |
本文作者:n1ce2cv
本文链接:https://www.cnblogs.com/sprinining/p/18449409
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2021-10-06 RecyclerView刷新方式