33-N皇后问题

n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击。

给定一个整数n,返回所有不同的n皇后问题的解决方案。

每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个女王和一个空位置。

样例

对于4皇后问题存在两种解决的方案:

[

[".Q..", // Solution 1

"...Q",

"Q...",

"..Q."],

["..Q.", // Solution 2

"Q...",

"...Q",

".Q.."]

]

挑战

你能否不使用递归完成?

标签

递归 深度优先搜索

方法一:递归方式--回溯算法

  1. 清空棋盘,rowIndex设为第一行,colIndex设为第一列

  2. 判断棋盘上rowIndex、colIndex的位置是否满足条件(即保证经过这一点的行,列与斜对角线上都没有两个皇后),

    若不满足,跳到第4步

  3. 在rowIndex、colIndex的位置上满足条件的情形:

    • 在当前位置放一个皇后,若rowIndex是最后一行,记录一个解
    • 若rowIndex不是最后一行,rowIndex++, colIndex=0
    • 若rowIndex是最后一行,colIndex不是最后一列, colIndex++
    • 若rowIndex是最后一行,colIndex是最后一列,回溯,即清空当前行及以下各行的棋盘,然后,rowIndex--, colIndex=0

      以上返回到第2步
  4. 在rowIndex、colIndex的位置上不满足条件的情形:

    • 若colIndex不是最后一列,colIndex设为下一列,返回到第2步
    • 若colIndex是最后一列了,回溯,即,若rowIndex行已经是第一行了,算法退出,否则,清空rowIndex及以下各行的棋盘,然后,rowIndex设为上一行,colIndex设为rowIndex的下一个待测位置,返回到第2步

把棋盘存储为一个N维数组a[N],数组中第i个元素的值代表第i行的皇后位置,这样便可以把问题的空间规模压缩为一维O(N),在判断是否冲突时也很简单,首先每行只有一个皇后,且在数组中只占据一个元素的位置,行冲突就不存在了,其次是列冲突,判断一下是否有a[i]与当前要放置皇后的列j相等即可。至于斜线冲突,通过观察可以发现所有在斜线上冲突的皇后的位置都有规律即它们所在的行列互减的绝对值相等,即| row – i | = | col – a[i] | 。这样某个位置是否可以放置皇后的问题已经解决。转自此博客

code

  1. class Solution {
  2. public:
  3. /**
  4. * Get all distinct N-Queen solutions
  5. * @param n: The number of queens
  6. * @return: All distinct solutions
  7. * For example, A string '...Q' shows a queen on forth position
  8. */
  9. vector<vector<string> > solveNQueens(int n) {
  10. // write your code here
  11. if(n == 1) {
  12. vector<vector<string> > result;
  13. vector<string> strOneRow;
  14. strOneRow.push_back("Q");
  15. result.push_back(strOneRow);
  16. return result;
  17. }
  18. else if(n < 4) {
  19. return vector<vector<string> > ();
  20. }
  21. vector<vector<string> > result;
  22. int i;
  23. int *pCheckerboard = new int[n];
  24. for(i=0; i<n; i++) {
  25. pCheckerboard[i] = -1;
  26. }
  27. queensRecursively(0, n, pCheckerboard, result);
  28. delete[] pCheckerboard;
  29. return result;
  30. }
  31. void queensRecursively(int row, int n, int *pCheckerboard, vector<vector<string> > &result) {
  32. int i = 0, j = 0;
  33. if(n == row) {
  34. vector<string> strOneRow;
  35. for(i=0; i<n; i++) {
  36. string str;
  37. for(j=0; j<n; j++) {
  38. str += '.';
  39. }
  40. if(pCheckerboard[i]>=0 && pCheckerboard[i]<n) {
  41. str[pCheckerboard[i]] = 'Q';
  42. }
  43. strOneRow.push_back(str);
  44. }
  45. result.push_back(strOneRow);
  46. }
  47. else {
  48. for(i=0; i<n; i++) {
  49. if(canPlace(row, i, n, pCheckerboard)) {
  50. pCheckerboard[row] = i;
  51. queensRecursively(row+1, n, pCheckerboard, result);
  52. }
  53. }
  54. }
  55. }
  56. int canPlace(int row, int col, int n, int *pCheckerboard) {
  57. int i;
  58. for(i=0; i<n && i!=row; i++) {
  59. if(pCheckerboard[i] == col) {
  60. return 0;
  61. }
  62. if(abs(row-i) == abs(col-pCheckerboard[i])) {
  63. return 0;
  64. }
  65. }
  66. return 1;
  67. }
  68. };

方法二:非递归

非递归方法的一个重要问题时何时回溯及如何回溯的问题。程序首先对N行中的每一行进行探测,寻找该行中可以放置皇后的位置,具体方法是对该行的每一列进行探测,看是否可以放置皇后,如果可以,则在该列放置一个皇后,然后继续探测下一行的皇后位置。如果已经探测完所有的列都没有找到可以放置皇后的列,此时就应该回溯,把上一行皇后的位置往后移一列,如果上一行皇后移动后也找不到位置,则继续回溯直至某一行找到皇后的位置或回溯到第一行,如果第一行皇后也无法找到可以放置皇后的位置,则说明已经找到所有的解程序终止。如果该行已经是最后一行,则探测完该行后,如果找到放置皇后的位置,则说明找到一个结果,打印出来。但是此时并不能再此处结束程序,因为我们要找的是所有N皇后问题所有的解,此时应该清除该行的皇后,从当前放置皇后列数的下一列继续探测。转自此博客

code

  1. class Solution {
  2. public:
  3. /**
  4. * Get all distinct N-Queen solutions
  5. * @param n: The number of queens
  6. * @return: All distinct solutions
  7. * For example, A string '...Q' shows a queen on forth position
  8. */
  9. vector<vector<string> > solveNQueens(int n) {
  10. // write your code here
  11. if(n == 1) {
  12. vector<vector<string> > result;
  13. vector<string> strOneRow;
  14. strOneRow.push_back("Q");
  15. result.push_back(strOneRow);
  16. return result;
  17. }
  18. else if(n < 4) {
  19. return vector<vector<string> > ();
  20. }
  21. vector<vector<string> > result;
  22. int i=0, row=0, col=0, j=0, k=0;
  23. int *pCheckerboard = new int[n];
  24. for(i=0; i<n; i++) {
  25. pCheckerboard[i] = -1;
  26. }
  27. while(row < n) {
  28. while(col < n) {
  29. if(canPlace(row, col, n, pCheckerboard)) {
  30. pCheckerboard[row] = col;
  31. col = 0;
  32. break;
  33. }
  34. else {
  35. col++;
  36. }
  37. }
  38. if(pCheckerboard[row] == -1) {
  39. if(row == 0) {
  40. break;
  41. }
  42. else {
  43. row--;
  44. col = pCheckerboard[row] + 1;
  45. pCheckerboard[row] = -1;
  46. continue;
  47. }
  48. }
  49. if(row == n-1) {
  50. vector<string> strOneRow;
  51. for(k=0; k<n; k++) {
  52. string str;
  53. for(j=0; j<n; j++) {
  54. str += '.';
  55. }
  56. if(pCheckerboard[k]>=0 && pCheckerboard[k]<n) {
  57. str[pCheckerboard[k]] = 'Q';
  58. }
  59. strOneRow.push_back(str);
  60. }
  61. result.push_back(strOneRow);
  62. col = pCheckerboard[row] + 1;
  63. pCheckerboard[row] = -1;
  64. continue;
  65. }
  66. row++;
  67. }
  68. delete[] pCheckerboard;
  69. return result;
  70. }
  71. int canPlace(int row, int col, int n, int *pCheckerboard) {
  72. int i;
  73. for(i=0; i<n && i!=row; i++) {
  74. if(pCheckerboard[i] == col) {
  75. return 0;
  76. }
  77. if(abs(row-i) == abs(col-pCheckerboard[i])) {
  78. return 0;
  79. }
  80. }
  81. return 1;
  82. }
  83. };

lintcode-33-N皇后问题的更多相关文章

  1. 33 N皇后问题

    原题网址:https://www.lintcode.com/zh-cn/old/problem/n-queens/# n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击. 给定一个整 ...

  2. dfs 解决八皇后问题 以及其他图搜索问题

    33. N皇后问题 中文 English n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线). 给定一个整数n,返回所有不同的n皇后问 ...

  3. 极限编程,最强N皇后JAVA解题代码,4秒出15皇后,33秒出16皇后

    私人博客原文链接来自:http://www.hexcode.cn/article/show/eight-queen 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化 8皇后以 ...

  4. 【LeetCode/LintCode】丨Google面试题:N皇后问题

    n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线). 给定一个整数n,返回所有不同的n皇后问题的解决方案. 每个解决方案包含一个明确的 ...

  5. lintcode 中等题:N Queens II N皇后问题 II

    题目: N皇后问题 II 根据n皇后问题,现在返回n皇后不同的解决方案的数量而不是具体的放置布局. 样例 比如n=4,存在2种解决方案 解题: 和上一题差不多,这里只是求数量,这个题目定义全局变量,递 ...

  6. lintcode 中等题:N Queens N皇后问题

    题目: N皇后问题 n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击.<不同行,不同列,不同对角线> 给定一个整数n,返回所有不同的n皇后问题的解决方案. 每个解决方案 ...

  7. [LintCode]——目录

    Yet Another Source Code for LintCode Current Status : 232AC / 289ALL in Language C++, Up to date (20 ...

  8. (lintcode全部题目解答之)九章算法之算法班题目全解(附容易犯的错误)

    --------------------------------------------------------------- 本文使用方法:所有题目,只需要把标题输入lintcode就能找到.主要是 ...

  9. 54. 八皇后问题[eight queens puzzle]

    [本文链接] http://www.cnblogs.com/hellogiser/p/eight-queens-puzzle.html [题目] 在8×8的国际象棋上摆放八个皇后,使其不能相互攻击,即 ...

  10. 八皇后问题 --- 递归解法 --- java代码

    八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上.八皇后 ...

随机推荐

  1. 入口文件 index.php 隐藏

    入口文件 index.php 隐藏 在PHP的web项目中,问了隐藏项目的开发语言,我们首先会选择把项目的入口文件index.php(如果做了特殊配置,特殊处理)在URL中隐藏掉. 当然部署中还需要隐 ...

  2. 新系统设置 github 私钥

    1.首先我得重新在git设置一下身份的名字和邮箱(因为当初都忘了设置啥了,因为遇到坑了)进入到需要提交的文件夹底下(因为直接打开git Bash,在没有路径的情况下,根本没!法!改!刚使用git时遇到 ...

  3. 从零开始一个http服务器(二)-请求request解析

    从零开始一个http服务器 (二) 代码地址 : https://github.com/flamedancer/cserver git checkout step2 解析http request 观察 ...

  4. 剑指offer题目系列三(链表相关题目)

    本篇延续上一篇剑指offer题目系列二,介绍<剑指offer>第二版中的四个题目:O(1)时间内删除链表结点.链表中倒数第k个结点.反转链表.合并两个排序的链表.同样,这些题目并非严格按照 ...

  5. SpaceVim 语言模块 dart

    原文连接: https://spacevim.org/cn/layers/lang/dart/ 模块简介 功能特性 依赖安装及启用模块 启用模块 语法检查及代码格式化 安装 dart-repl 快捷键 ...

  6. PPAS下安装 pg_stat_statements过程记录

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL统计信息索引页     回到顶级页面:PostgreSQL索引页 PostgreSQL中,如何安装pg_stat_sta ...

  7. ORB-SLAM(五)KeyFrameDataBase类

    关键帧数据库通过预先训练好的词典,维护一个向量std::vector<list<KeyFrame*> > mvInvertedFile; 该向量中mvInvertedFile[ ...

  8. Flume直接对接SaprkStreaming的两种方式

    一.flume对接sparkStreaming的两种方式: Push推送的方式 Poll拉取的方式 第一种Push方式: 代码如下: package cn.itcast.spark.day5 impo ...

  9. 【公司动态添加行】前台穿一个json的字符串到后台,并解析

    <!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...

  10. 网易云易盾与A10 Networks达成战略合作 携手打造抗DDoS攻击的解决方案

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 2018年9月,网易云易盾宣布,与智能和自动化网络安全解决方案提供商A10 Networks结成战略合作伙伴关系.双方将在抗DDoS攻击领域展开深入 ...