淘先锋技术网

首页 1 2 3 4 5 6 7

皇后问题求解

(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 +  };
    struct Pos : public Object
    {
        int x;
        int y;
        Pos(int px = , int py = ) : x(px), y(py) { }
    };

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

    void init()
    {
        m_count = ;

        // 定义0代表空位置,1代表皇后,2代表棋盘边界
        // 初始化棋盘边界
        for(int i=; i<N; i+=(N-))
        {
            for(int j=; j<N; j++)
            {
                m_chessboard[i][j] = ;
                m_chessboard[j][i] = ;
            }
        }

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

        m_direction[].x = -;      // 向左下角扫描
        m_direction[].y = -;
        m_direction[].x = ;       // 向下扫描
        m_direction[].y = -;
        m_direction[].x = ;       // 向右下角扫描
        m_direction[].y = -;
    }

    void print()
    {
        // 遍历位置坐标链表,输出棋盘上皇后的坐标
        for(m_solution.move(); !m_solution.end(); m_solution.next())
        {
            cout << "(" << m_solution.current().x << ", " << m_solution.current().y << ") ";
        }
        cout << endl;

        // 打印棋盘
        for(int i=; i<N; i++)
        {
            for(int j=; j<N; j++)
            {
                switch(m_chessboard[i][j])
                {
                case : cout << " "; break;
                case : cout << "#"; break;
                case : 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] == );
        }
        while(flag);

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


    // 检查第j行有没有可以放置皇后的位置
    void run(int j)
    {
        if(j <= SIZE)
        {
            for(int i=; i<=SIZE; i++)
            {
                // 检查在三个方向上都没有其它皇后满足时,才能够放置皇后
                if(check(i, j, ) && check(i, j, ) && check(i, j, ))
                {
                    m_chessboard[i][j] = ;     // 当前位置可以放置皇后

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

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

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

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

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

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

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


};

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

    return ;
}

(4)实现结果:
这里写图片描述