学校数据结构的课程实验之一。

数据结构:(其实只用了一个二维数组)

算法:深度优先搜索,试探回溯

需求分析:

  设计一个在控制台窗口运行的“n皇后问题”解决方案生成器,要求实现以下功能:

  由n*n个方块排成n行n列的正方形称为n元棋盘。如果两个皇后位于n元棋盘上的同一行、同一列或同一对角线上,则称它们在互相攻击。现要找出使棋盘上n个皇后互不攻击的布局。

  编制程序解决上述问题,以n=6运行程序,输出结果。

算法解释:

  首先试探当前行第一个可用的位置(列、对角线没有被占领),摆放皇后之后,试探下一行的第一个可用位置;如果遇到此行没有可用位置,则返回上一行,移除上一行的皇后,试探此行的下一个可用位置,直至n个皇后全部摆放好,生成一种方案。

主函数:

  1. int main()
  2. /*Pre: The user enters a valid board size.
  3. Post: All solutions to the n-queens puzzle for the selected board size
  4. are printed.
  5. Uses: The class Queens and the recursive functionsolve from. */
  6. {
  7. int board_size;
  8. char choice = 'y';
  9. char enter;
  10. while (choice == 'y')//由用户决定是否继续
  11. {
  12. sum = ;
  13. cout << "What is the size of the board?"<<flush;
  14. cin >> board_size;
  15. if(board_size < ||board_size > max_board)
  16. cout<<"The number must between 0 and "<<max_board<<endl;
  17. else
  18. {
  19. Queens configuration(board_size);//创建size*size的对象
  20.  
  21. cout << "there is total " << solve_from(configuration) << " configurations." << endl;//打印所有解决方案和方案个数
  22. }
  23. cout << endl << "Would you like to continue? [y/n]" << endl;
  24. //回车符的消去
  25. fflush(stdin);
  26. while ((enter = cin.get()) == '\n')
  27. {
  28. enter = cin.get();
  29. }
  30. cin.putback(enter);
  31. cin >> choice;//移植了计算器的代码
  32. }
  33. return ;
  34. }

辅助函数(计算出所有解决方案)(参考了经典教材"Data Structures and Program Design in C++" Robert L. Kruse, Alexander J. Ryba 高等教育出版社-影印版)

  1. int sum = ;//记录解决方案个数
  2.  
  3. int solve_from(Queens &configuration)//通过递归、回溯找到所有解决方案并打印
  4. /*Pre: the queens configuration represents a partially completed
  5. arrangement of nonattacking queens on a chessboard.
  6. Post: all n-queens solutions that extend the given configuration are
  7. printed. The configuration is restored to its initial state.
  8. Uses: the class Queens and the function solve_from, recursively.*/
  9. {
  10. if (configuration.is_solved())//当生成一种解决方案时打印,sum自增一
  11. {
  12. sum++;
  13. configuration.print();
  14. cout <<"================" <<endl;
  15. }
  16. else
  17. for(int col=; col<configuration.board_size; col++)
  18. if(configuration.unguarded(col))
  19. {
  20. configuration.insert(col);
  21. solve_from(configuration);//recursively continue to add queens当生成一种解决方案时打印
  22. configuration.remove(col);//return the last row and the last col.试探上一层的下一种方案(无论上一次试探是成功还是失败)
  23. }
  24. return sum;
  25. }

注:

  每次回溯其实有两种可能:“摆放满了n个皇后”或者“此行没有可放的位置”,二者都会返回上一行去试探下一种可能,只不过摆满n个皇后的情况会生成一种方案(被if截获,回到上一层循环),生成后还是回到倒数第二行再进行试探。因此一次深度优先搜索(调用一次solve_from函数)可以将所有方案全部输出。

“皇后”类的定义

  1. const int max_board = ;//最大棋盘阶数
  2. using namespace std;
  3.  
  4. class Queens
  5. {
  6. public:
  7. Queens(int size);
  8. bool is_solved() const;//判断是否完成一种方案
  9. void print() const;//打印当前方案
  10. bool unguarded(int col) const;//判断某格是否可放皇后
  11. void insert(int col);//摆放皇后
  12. void remove(int col);//移除
  13. int board_size;//dimension of board = maximum number of queens
  14. private:
  15. int count;//current number of queens = first unoccupied row
  16. bool queen_square[max_board][max_board];//存放棋盘状态的二维数组
  17. };

“皇后”类的实现(同样参考了经典教材"Data Structures and Program Design in C++" Robert L. Kruse, Alexander J. Ryba 高等教育出版社-影印版)

  1. #include <iostream>
  2. #include "Queens.h"
  3.  
  4. Queens::Queens(int size)
  5. {
  6. board_size = size;
  7. count = ;//从第一行开始计数
  8. for(int row=; row<board_size; row++)
  9. for(int col=; col<board_size; col++)
  10. queen_square[row][col] = false;//生成size*size的空棋盘
  11. }
  12.  
  13. bool Queens::is_solved() const
  14. /*whether the number of queens already placed
  15. equals board_size*/
  16. {
  17. bool solved = false;
  18. if(count == board_size)//当board_size个皇后都摆放完毕时,生成一种方案
  19. solved = true;
  20. return solved;
  21. }
  22.  
  23. void Queens::print() const
  24. {
  25. for (int row = ; row < board_size; row++)
  26. {
  27. for (int col = ; col < board_size; col++)
  28. if (queen_square[row][col] == true)
  29. cout << "* ";
  30. else
  31. cout << "_ ";//逐个打印棋盘元素,有皇后打印'*',无皇后打印'_'
  32. cout << endl;
  33. }
  34. }
  35.  
  36. bool Queens::unguarded(int col) const
  37. /*Post: Return true or false according as the square in the first
  38. unoccupied row(row count) and colum col is not guarded by andy queen*/
  39. {
  40. int i;
  41. bool ok = true;//turn false if we find a queen in column or diagonal
  42. for(i=; ok && i < count; i++)
  43. ok = !queen_square[i][col];//check upper part of column同列
  44. for(i=; ok && count-i >= && col-i >=; i++)
  45. ok = !queen_square[count-i][col-i];//check upper-left diagonal
  46. for(i=; ok && count-i >= && col+i < board_size; i++)
  47. ok = !queen_square[count-i][col+i];//chekck upper-right diagonal
  48. return ok;
  49. }
  50.  
  51. void Queens::insert(int col)
  52. /*Pre: The square in the first unoccupied row(row count) and column is not
  53. guarded by any queen.
  54. Post: A queen has been inserted into the square at row count and column col;
  55. count has been incremented by 1*/
  56. {
  57. queen_square[count++][col] = true;//放入皇后,计数器自增一(到下一行)
  58. }
  59.  
  60. void Queens::remove(int col)
  61. /*Pre: there is a queen in the square in row count-1 and column col.
  62. Post: the above queen has been removed; count has been decremented by 1.*/
  63. {
  64. queen_square[count-][col] = false;//移出皇后,计数器自减一(回上一行)
  65. count--;
  66. }

Queen.cpp

运行截图:

注:

  当输入的棋盘阶数比较大(如:8)时,命令行窗口的缓冲区默认300行可能会不够显示,所以要在属性修改“高度”,使所有结果都显示出来。

用试探回溯法解决N皇后问题的更多相关文章

  1. 回溯法解决N皇后问题(以四皇后为例)

    以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...

  2. C++使用回溯法实现N皇后问题的求解

    回溯法是个很无聊的死算方法,没什么技巧,写这篇博客主要原因是以前思路不太清晰,现在突然想用回溯法解决一个问题时,无法快速把思路转换成代码. ------------------------------ ...

  3. Python基于回溯法解决01背包问题实例

    Python基于回溯法解决01背包问题实例 这篇文章主要介绍了Python基于回溯法解决01背包问题,结合实例形式分析了Python回溯法采用深度优先策略搜索解决01背包问题的相关操作技巧,需要的朋友 ...

  4. 回溯法求解n皇后和迷宫问题

    回溯法是一种搜索算法,从某一起点出发按一定规则探索,当试探不符合条件时则返回上一步重新探索,直到搜索出所求的路径. 回溯法所求的解可以看做解向量(n皇后坐标组成的向量,迷宫路径点组成的向量等),所有解 ...

  5. 回溯算法——解决n皇后问题

    所谓回溯(backtracking)是通过系统地搜索求解问题的方法.这种方法适用于类似于八皇后这样的问题:求得问题的一个解比较困难,但是检查一个棋局是否构成解很容易. 不多说,放上n皇后的回溯问题代码 ...

  6. USACO 1.5.4 Checker Challenge跳棋的挑战(回溯法求解N皇后问题+八皇后问题说明)

    Description 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行,每列,每条对角线(包括两条主对角线的所有对角线)上都至多有一个棋子. 列号 0 1 2 3 4 5 6 ...

  7. C语言回溯算法解决N皇后问题

    回溯算法的模型是 x++, not satisfy ? x-- : continue. 代码中x作列号,y[x]保存第x列上皇后放置的位置. #include<stdio.h> #incl ...

  8. 回溯法——求解N皇后问题

    问题描写叙述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后.使其不能互相攻击,即随意的两个皇后不能处在允许行.同一列,或允许斜线上. 能够把八皇后问题拓展 ...

  9. 试探回溯法(backtracking)

    一.八皇后问题 国际象棋中皇后的势力范围覆盖其所在的水平线.垂直线以及两条对角线.现考查如下问题:在n*n的棋盘上放置n个皇后,如何使得她们彼此互不攻击,此时称她们构成一个可行的棋局.对于任何整数n ...

随机推荐

  1. Controller 中Action 返回值类型 及其 页面跳转的用法

        •Controller 中Action 返回值类型 View – 返回  ViewResult,相当于返回一个View 页面. -------------------------------- ...

  2. hdu2059 龟兔赛跑

    hdu2059 龟兔赛跑 动态规划 题目描述: Problem Description 据说在很久很久以前,可怜的兔子经历了人生中最大的打击——赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州 ...

  3. 类linux 系统iptables 系统初始化配置

    #!/bin/bash iptables -F iptables -X /etc/rc.d/init.d/iptables save service iptables restart iptables ...

  4. yii2学习的论坛

    http://www.yiifans.com/forum.php http://www.yiichina.com/ http://www.yiichina.com/

  5. jmock2.5基本教程(转)

    原文:http://www.cnblogs.com/zfc2201/archive/2011/12/30/2307970.html jmock2.5基本教程 目录 第0章 概述 第1章 jmock初体 ...

  6. 用JUnit4进行参数化测试

    参数化测试是一个JUnit 3不具备的功能. 基本使用方法 @RunWith 当类被@RunWith注解修饰,或者类继承了一个被该注解修饰的类,JUnit将会使用这个注解所指明的运行器(runner) ...

  7. 在Maven的配置文件中,自定义私有仓库地址和设置下载的jar包的保存位置

    在Maven的settings.xml,可以设置Maven的私有仓库的地址,还可以设置所下载jar包在自己电脑的保存地址(默认不设置保存在个人文件夹的.m2文件夹下). 1.设置私有仓库地址: < ...

  8. Timer.3 - Binding arguments to a handler

    In this tutorial we will modify the program from tutorial Timer.2 so that the timer fires once a sec ...

  9. Android开发:shape和selector和layer-list的(详细说明)

    http://blog.csdn.net/brokge/article/details/9713041

  10. axure 8.0 动态特效库分享

    认准品牌 六脉神掌 尽量给每一个交互加上效果,尽量模拟真实的交互 无图无真相,我们先看效果图 1 这是还原Android Material Design风格的一个底部菜单效果 2 这个是模拟欢迎页面 ...