【递归】 LeetCode51. N皇后

分手后的思念是犯贱 2022-12-03 05:21 255阅读 0赞

题目

在这里插入图片描述在这里插入图片描述

解答

回溯法的求解过程实质上是一个先序遍历一棵状态树的过程,只是这棵树不是遍历前预先建立的,而是隐含在遍历的过程中。

递归题的解法:首先把题目的决策树画出来,树的层就是for循环,树的深度就是要递归的参数i。画出决策树后,找规律,进行剪枝。

皇后横竖斜方向的棋子都会被吃掉,棋盘每行只能放一个皇后。

E.g. 输入 n = 4

树的层为棋子放入棋盘哪一列,树的深度为放入棋盘哪一行。
在这里插入图片描述

代码

  1. #include <iostream>
  2. #include <string>
  3. #include <list>
  4. #include <vector>
  5. #include <map>
  6. #include <utility>
  7. #include <functional>
  8. #include <algorithm>
  9. #include <cassert>
  10. // 51. N-Queens
  11. // 使用std::vector<std::vector<int>> chessboard来标记棋盘所有被攻击的位置为1,没有被攻击的位置为0。
  12. // 将皇后放到(x,y)并且标记其所有的攻击位置。
  13. void MarkAttackPosition(int x, int y, std::vector<std::vector<int>>& chessboard) {
  14. // (x,y)这个点上下左右斜对角九个点,相对于x的偏移量。(X,Y)= N(dx,dy) + (x,y)
  15. static const int N = 9;
  16. static const int dx[N] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 };
  17. static const int dy[N] = { -1, 0, 1, -1, 0, 1, -1, 0, 1};
  18. const int kChessboardLen = chessboard.size();
  19. for (int i = 0; i < kChessboardLen; i++) {
  20. for (int j = 0; j < N; j++) {
  21. int temp_x = x + i * dx[j];
  22. int temp_y = y + i * dy[j];
  23. if (temp_x < 0 || temp_y < 0 || temp_x >= kChessboardLen || temp_y >= kChessboardLen) {
  24. continue;
  25. }
  26. chessboard[temp_x][temp_y] = 1;
  27. }
  28. }
  29. }
  30. // 回溯法的求解过程实质上是一个先序遍历一棵状态树的过程,只是这棵树不是遍历前预先建立的,而是隐含在遍历的过程中。
  31. // 所以解答此类题的关键就是找到这棵树,然后将题目转化为遍历树的过程。
  32. // i 代表行,j代表列。一行一行的去放值,首先放置在第一行,然后依次尝试放在每一列,尝试一个可行列后继续放下一行。可以展开成一棵树。
  33. void PlaceQueen(int i, int n,
  34. std::vector<std::vector<int>>& chessboard,
  35. std::vector<std::string>& subset,
  36. std::vector<std::vector<std::string>>& subsets) {
  37. if (i >= n) {
  38. subsets.push_back(subset);
  39. return;
  40. }
  41. for (int j = 0; j < n; ++j) {
  42. if (chessboard[i][j] == 1) {
  43. continue;
  44. }
  45. std::vector<std::vector<int>> backup_chessboard = chessboard;
  46. // 尝试放在(i, j)。
  47. MarkAttackPosition(i, j, chessboard);
  48. subset[i][j] = 'Q';
  49. PlaceQueen(i + 1, n, chessboard, subset, subsets);
  50. // 接下来将尝试放在(i, j+1)这个位置,所以要恢复到之前的状态。
  51. subset[i][j] = '.';
  52. chessboard = backup_chessboard;
  53. }
  54. }
  55. std::vector<std::vector<std::string>> solveNQueens(int n) {
  56. std::vector<std::vector<std::string>> subsets;
  57. std::vector<std::string> subset(n, std::string(n, '.'));
  58. std::vector<std::vector<int>> chessboard(n, std::vector<int>(n, 0));
  59. PlaceQueen(0, n, chessboard, subset, subsets);
  60. return subsets;
  61. }
  62. void PrintChessboard(const std::vector<std::vector<int>>& chessboard) {
  63. for (const auto& line : chessboard) {
  64. for (auto i : line) {
  65. std::cout << i;
  66. }
  67. std::cout << std::endl;
  68. }
  69. }
  70. void PrintSubsets(const std::vector<std::vector<std::string>>& subsets) {
  71. for (const auto& subset : subsets) {
  72. for (const auto& line : subset) {
  73. std::cout << line << std::endl;
  74. }
  75. std::cout << "------------------------" << std::endl;
  76. }
  77. }
  78. int main() {
  79. PrintSubsets(solveNQueens(8));
  80. return 0;
  81. }

发表评论

表情:
评论列表 (有 0 条评论,255人围观)

还没有评论,来说两句吧...

相关阅读

    相关 leetcode 51N皇后 52N皇后II

    n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 上图为 8 皇后问题的一种解法。 给定一个整数 n,返回所有不同的 n 皇

    相关 LeetCode 51. N皇后

    题目重述 n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方

    相关 leetcode:51. N皇后

    题目: n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 上图为 8 皇后问题的一种解法。 给定一个整数 n,返回所有

    相关 Leetcode51N皇后

    n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 思路: 刚开始的思路是,用一个二维int数组来保存,后来发现很繁琐,其次就