实现n皇后问题的多种解法
发布日期:2021-05-20 07:54:52 浏览次数:23 分类:精选文章

本文共 3265 字,大约阅读时间需要 10 分钟。

n皇后问题解法与改进算法探讨

常规问题一:回溯法解法

回溯法思路

传统的n皇后问题可以通过回溯法解决。具体步骤如下:

  • 从当前行i开始,逐个尝试将皇后放置在列j。
  • 判断放置的位置是否合法:
    • 列j是否已有皇后?
    • 是否在同一45°对角线?判断条件为i + j是否已存在于diag45集合中。
    • 是否在同一135°对角线?判断条件为i - j是否已存在于diag135集合中。
  • 若位置合法,将皇后放置在(i, j),并记录相关约束。
  • 若上一行完成,则递归处理下一行;否则回退到上一行,尝试下一列。
  • 回溯法代码实现

    #include 
    #include
    #include
    #include
    using namespace std;void Backtracking(int N, int i, set
    col, set
    diag45, set
    diag135, vector
    placeResult, int &ans) { int j = 1; while (i <= N && i > 0) { while (j <= N) { if (!col.count(j) && !diag45.count(i + j) && !diag135.count(i - j)) { placeResult[i] = j; col.insert(j); diag45.insert(i + j); diag135.insert(i - j); i++; j = 1; break; } j++; } if (j > N) { j = Erase(i, col, diag45, diag135, placeResult); } if (i == N + 1) { ans++; for (int row = 1; row <= N; row++) { for (int col = 1; col <= N; col++) { if (col == placeResult[row]) { printf("√"); } else if (col != N) { printf(" "); } else { printf("\n"); } } } printf("\n"); } }}void Erase(int &i, set
    col, set
    diag45, set
    diag135, vector
    placeResult) { i--; int k = placeResult[i]; placeResult[i] = 0; col.erase(k); diag45.erase(i + k); diag135.erase(i - k); return k + 1;}// 该函数将皇后随机放置在前stepVegas行,后面的皇后按传统回溯法解决bool QueenLV(int N, set
    col, set
    diag45, set
    diag135, vector
    placeResult, int stepVegas) { int i = 1; int LP = 0; �� Coronation:

    常规问题二:全排列枚举法

    全排列枚举思路

    使用全排列算法,生成所有可能的皇后位置排列。只需验证对角线约束即可。

  • 生成列数组P[1..n],表示每一行放置的相应列号。
  • 递归验证每个排列是否满足不在同一对角线的条件:
    • 检查每两个皇后之间的斜距是否为1。
  • 全排列枚举代码

    #include 
    #include
    using namespace std;void generateP(vector
    &P, vector
    &isLegal, int n, int &ans, int index) { if (index == n + 1) { ans++; return; } for (int i = 1; i <= n; i++) { if (!isLegal[i]) { bool flag = true; for (int pre = 1; pre < index; pre++) { if (abs(index - pre) == abs(i - P[pre])) { flag = false; break; } } if (flag) { P[index] = i; isLegal[i] = true; generateP(P, isLegal, n, ans, index + 1); isLegal[i] = false; } } }}int main() { int n = 8; vector
    P(n + 1); vector
    isLegal(n + 1); int ans = 0; generateP(P, isLegal, n, ans, 1); printf("有%d种放置可能\n", ans); return 0;}

    另一类问题:Las Vegas思想优化

    优化思路

    前stepVegas行采用随机放置,剩余行用传统回溯法解决。

  • 在stepVegas行处随机选择合法位置放置皇后。
  • 放置成功后,后steps按传统回溯法完成。
  • 若未能在stepVegas行找到合法位置,返回失败。
  • 优化结果分析

    实验表明,stepVegas取略小于N的值时效果较好,步长如下:N = 8时,stepVegas = 7N = 15时,stepVegas = 13

    这种方法相比纯回溯方法平均所需时间较少。

    运行示例

    如N=8,stepVegas=7与stepVegas=8的对比结果表明,stepVegas=7的平均首次成功所需时间更短。

    扩展阅读

  • [皇后问题回溯法](https:// курс在线)
  • [全排列枚举解法](https:// )
  • [Las Vegas思想优化](https:// )
  • 上一篇:C++11 for循环的新写法(用于实现LeetCode238.移除零)
    下一篇:VSCode配置C/C++环境及注意事项

    发表评论

    最新留言

    做的很好,不错不错
    [***.243.131.199]2025年04月26日 15时04分29秒