码迷,mamicode.com
首页 > 其他好文 > 详细

八皇后问题(N皇后问题)

时间:2018-02-12 16:45:28      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:bsp   case   std   设置   body   public   print   png   ring   

首先来看看这张模拟八皇后的图。
技术分享图片
下面这张黑色背景是其中一个方案的截图,第一行代表皇后的坐标;后面的是棋盘,其中*是边界,空格是空区,#是皇后。
技术分享图片
#include <iostream>
#include <cstring>
#include "DTString.h"
#include "LinkList.h"  // 这里使用链表存储皇后位置

using namespace std;
using namespace DTLib;

template <int SIZE>             // N皇后问题,SIZE表示皇后个数或者棋盘大小
class QueenSolution : public Object
{
protected:
    enum { N = SIZE + 2 };      // 为了边界识别,棋盘四周都要加一格

    struct Pos : public Object  // 方位结构体
    {
        Pos(int px = 0, int py = 0) : x(px), y(py) { }
        int x;
        int y;
    };

    int m_chessboard[N][N];     // 棋盘,0表示空位,1表示皇后,2表示边界
    Pos m_direction[3];         // 方向-1,-1表示左斜线;0,-1表示下方;1,-1表示右斜线;首先从最下方开始,所以只需考虑前面的行。
    LinkList<Pos> m_solution;   // 用链表记录解决方案
    int m_count;                // 记录有效方案数量

    void init()
    {
        m_count = 0;                    // 有效方案初始化为0

        for(int i=0; i<N; i+=(N-1))     // 遍历第0行和最后一行
        {
            for(int j=0; j<N; j++)      // 遍历每一列
            {
                m_chessboard[i][j] = 2; // 给棋盘的上下设置边界
                m_chessboard[j][i] = 2; // 给棋盘的左右设置边界
            }
        }

        for(int i=1; i<=SIZE; i++)      // 初始化棋盘为空位
        {
            for(int j=1; j<=SIZE; j++)
            {
                m_chessboard[i][j] = 0;
            }
        }

        m_direction[0].x = -1;          // 初始化方向数据
        m_direction[0].y = -1;
        m_direction[1].x = 0;
        m_direction[1].y = -1;
        m_direction[2].x = 1;
        m_direction[2].y = -1;
    }

    void print()                        // 打印有效方案,方案记录了坐标值
    {
        for(m_solution.move(0); !m_solution.end(); m_solution.next())   // 打印坐标
        {
            cout << "(" << m_solution.current().x << ", " << m_solution.current().y << ")" ;
        }

        cout << endl;                   // 坐标打印换行

        for(int i=0; i<N; i++)          // 打印棋盘
        {
            for(int j=0; j<N; j++)
            {
                switch(m_chessboard[i][j])
                {
                    case 0: cout << " "; break; // 空位
                    case 1: cout << "#"; break; // 皇后
                    case 2: cout << "*"; break; // 边界
                }
            }

            cout << endl;
        }

        cout << endl;                           // 棋盘打印完换行
    }

    bool check(int x, int y, int d)             // 检查是否可放置皇后
    {
        bool flag = true;

        do
        {
            x += m_direction[d].x;
            y += m_direction[d].y;
            flag = flag && (m_chessboard[x][y] == 0);// 查看坐标位置是否有空位
        }
        while( flag );                          // 本次循环后不会再有空位

        return (m_chessboard[x][y] == 2);       // 返回真就是到边界,否则就是有皇后
    }

    void run(int j) // 检查当前行有没有可放置皇后的位置
    {
        if( j <= SIZE ) // 检查当前行在棋盘内,注意不要跑到边界上
        {
            for(int i=1; i<=SIZE; i++)
            {
                if( check(i, j, 0) && check(i, j, 1) && check(i, j, 2) )    // 如果if为真表示可以放置皇后
                {
                    m_chessboard[i][j] = 1;                                 // 标记该处有皇后

                    m_solution.insert(Pos(i, j));                           // 记录皇后的位置到链表

                    run(j + 1);                                             // 递归判断下一行

                    m_chessboard[i][j] = 0;                                 // 回溯后要把棋盘当前位置的皇后清除,避免下一次调用时还有上次的皇后位置

                    m_solution.remove(m_solution.length() - 1);             // 回溯后记录皇后位置的链表长度也要减少
                }
            }
        }
        else    // 如果j大于SIZE就表示一轮检查结束,方案计数加1并打印方案
        {
            m_count++;

            print();
        }
    }

public:
    QueenSolution()
    {
        init();
    }

    void run()
    {
        run(1); // 从第一行开始,注意边界占用的行数(本例四周都占用了1行或列记录边界,所以从1开始)

        cout << "Total: " << m_count << endl;   // 输出方案个数
    }
};

int main()
{
    QueenSolution<8> qs;

    qs.run();

    return 0;
}

 

八皇后问题(N皇后问题)

标签:bsp   case   std   设置   body   public   print   png   ring   

原文地址:https://www.cnblogs.com/Dua677/p/8444515.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!