皇后问题求解
(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)实现结果: