国际象棋皇后问题

皇后问题求解

(1)八皇后问题:
《国际象棋皇后问题》
(2)求解思路:
《国际象棋皇后问题》
(3)代码实现:

#include <iostream>
#include "Object.h"
#include "LinkList.h"

using namespace std;
using namespace MyLib;

template <int SIZE>
class QueueSolution : public Object
{
protected:
    enum { N = SIZE + 2 };
    struct Pos : public Object
    {
        int x;
        int y;
        Pos(int px = 0, int py = 0) : x(px), y(py) { }
    };

    int m_chessboard[N][N];
    Pos m_direction[3];
    LinkList<Pos> m_solution;
    int m_count;

    void init()
    {
        m_count = 0;

        // 定义0代表空位置,1代表皇后,2代表棋盘边界
        // 初始化棋盘边界
        for(int i=0; i<N; i+=(N-1))
        {
            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;

            // 0代表的是空位置,判断在当前方向上是否有其它皇后,若有其它皇后,则循环标志量flag=false;循环退出,函数返回false,意味着在当前方向不能再有皇后;
            // 若没有其它皇后,则循环一直在当前方向上查找,直到碰到棋盘边界的代表值2,flag=false,循环退出,函数返回true,说明可以在当前方向上有皇后
            flag = flag && (m_chessboard[x][y] == 0);
        }
        while(flag);

        return (m_chessboard[x][y] == 2);
    }


    // 检查第j行有没有可以放置皇后的位置
    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))
                {
                    m_chessboard[i][j] = 1;     // 当前位置可以放置皇后

                    m_solution.insert(Pos(i, j));   // 将可以放置皇后的坐标保存

                    run(j + 1);     // 递归调用查看下一行是否可以放其它皇后

                    // 当run()函数调用返回时,说明当前位置不能放置皇后,则需要回溯,将之前的标记清空,并且删除链表保存的最后一个位置坐标元素
                    m_chessboard[i][j] = 0;
                    m_solution.remove(m_solution.length() - 1);
                }
            }
        }
        else
        {
            // else分支意味着已经查找完了棋盘,找到了一个解决方案
            m_count++;

            // 打印可行的解决方案
            print();
        }
    }

public:
    QueueSolution()
    {
        // 直接调用init()函数初始化所有数据
        init();
    }

    void run()
    {
        // 从棋盘的第一行开始查找放置皇后的位置
        run(1);

        cout << "Total: " << m_count << " methods" << endl;
    }


};

int main()
{
    QueueSolution<8> qs;
    qs.run();

    return 0;
}

(4)实现结果:
《国际象棋皇后问题》

    原文作者:八皇后问题
    原文地址: https://blog.csdn.net/feiyanaffection/article/details/79312641
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注