zoukankan      html  css  js  c++  java
  • 用试探回溯法解决N皇后问题

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

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

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

    需求分析:

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

      由n*n个方块排成nn列的正方形称为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 = 0;
    13         cout << "What is the size of the board?"<<flush;
    14         cin >> board_size;
    15         if(board_size < 0||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()) == '
    ')
    27         {
    28             enter = cin.get();
    29         }
    30         cin.putback(enter);
    31         cin >> choice;//移植了计算器的代码
    32     }
    33     return 0;
    34 }

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

     1 int sum = 0;//记录解决方案个数
     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=0; 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 = 15;//最大棋盘阶数
     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 = 0;//从第一行开始计数
     8     for(int row=0; row<board_size; row++)
     9         for(int col=0; 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 = 0; row < board_size; row++)
    26     {
    27         for (int col = 0; 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=0; ok && i < count; i++)
    43         ok = !queen_square[i][col];//check upper part of column同列
    44     for(i=1; ok && count-i >= 0 && col-i >=0; i++)
    45         ok = !queen_square[count-i][col-i];//check upper-left diagonal
    46     for(i=1; ok && count-i >= 0 && 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-1][col] = false;//移出皇后,计数器自减一(回上一行)
    65     count--;
    66 }
    Queen.cpp

    运行截图:

    注:

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

  • 相关阅读:
    android&php 加密解密
    AES加解密算法在Android中的应用及Android4.2以上版本调用问题
    eclipse 中 import sun.misc.BASE64Decoder; 报错
    Java加密技术(一)——加密介绍
    android加密DESede/CBC/PKCS5Padding
    Android中的Audio播放:竞争Audio之Audio Focus的应用
    java.lang.IllegalStateException: attempt to re-open an already-closed object
    Android 性能优化的一些方法
    android.os.DeadObjectException memory near r0: 异常处理 Consumer closed input channel or an error occurred. events=0x9
    如何分析解决Android ANR
  • 原文地址:https://www.cnblogs.com/helenawang/p/4426328.html
Copyright © 2011-2022 走看看