1.八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。
下面我将编程解决这个问题。
我首先把此问题的求解延伸到N皇后问题,考虑到可能输出的结果会很多,我设定如果结果数大于或等于N种则只输出N种结果,如果结果数小于N种则输出全部结果,结果输出至文件output.txt中,单个结果为N*N的二维矩阵,其中Q代表皇后,X代表空。
下面是代码:
QueensQuestion.h
#pragma once
#include <string>
class QueensQuestion
{
public:
QueensQuestion(int numOfQueen);
~QueensQuestion(void);
void answer();
private:
bool answer(int row);
int output();
int output(std::string &str);
private:
const int num;
const char queen ;
const char empty ;
char **chessboard;
std::string outputStr;
};
QueensQuestion.cpp
#include "QueensQuestion.h"
#include <iostream>
#include <fstream>
using namespace std;
QueensQuestion::QueensQuestion(const int numOfQueen)
:num(numOfQueen),queen('Q'),empty('X')
{
chessboard = new char*[num];
for (int i = 0; i != num ;++i)
{
chessboard[i] = new char[num];
}
}
QueensQuestion::~QueensQuestion(void)
{
for (int i = 0; i != num ;++i)
{
delete [] chessboard[i];
}
delete [] chessboard;
}
int QueensQuestion::output()
{
ofstream outFile("output.txt");
if (!outFile)
{
cout<<"写入文件output.txt失败!"<<endl;
return -1;
}
if(outputStr.empty())
{
cout<<"没有合适的方案!"<<endl;
return -2;
}
outFile<<outputStr<<endl;
outFile.close();
return 0;
}
int QueensQuestion::output(string &str)
{
for (int i = 0; i != num ; ++i)
{
for (int j = 0; j != num ; ++j)
{
str += chessboard[i][j];
}
str += "\n";
}
str += "\n";
return 0;
}
bool QueensQuestion::answer(int row)//第row行
{
for (int i=0 ; i!=num ; ++i)//第row行的第i个方格
{
bool judge = true;//判断是否不符合放棋要求,符合为true, 否则为false
for (int j = 1 ; (row-j) != -1 ; ++j)//前第j行
{
if( chessboard[row-j][i] == queen )
{
judge = false;
break;
}
if( chessboard[row-j][i-j] == queen )
{
judge = false;
break;
}
if( chessboard[row-j][i+j] == queen )
{
judge = false;
break;
}
}
if (judge)//如果chessboard [row][i]符合放棋要求
{
chessboard[row][i] = queen;
if ( row+1 == num )//最后一行
{
return true;
}
if ( answer(row+1) )//查找下一行
{
return true;
}
chessboard[row][i] = empty;//下一行不符合要求,清空当前方格,继续循环
}
}
return false;
}
void QueensQuestion::answer()
{
for (int i=0 ; i!=num; ++i) //以第一行为基准
{
for (int j=0; j!=num ; ++j) //初始化矩阵
{
for (int k=0; k!=num ; ++k)
{
chessboard[j][k] = empty;
}
}
chessboard[0][i] = queen; //放置第一行的Queen
if (answer(1))
{
output(outputStr);
}
}
if (0 == output())
cout<<"成功!计算结果详见output.txt"<<endl;
}
上面就是解决N皇后问题的类定义与实现。
以下是测试代码:
main.cpp
#include <iostream>
#include "QueensQuestion.h"
int main ()
{
int i = 0;
std::cout<<"请输入皇后的数目:";
std::cin>>i;
QueensQuestion *eQQ =new QueensQuestion(i);
eQQ->answer();
delete eQQ;
return 0;
}
程序运行结果:
output.txt内容如下:
QXXXXXXX
XXXXQXXX
XXXXXXXQ
XXXXXQXX
XXQXXXXX
XXXXXXQX
XQXXXXXX
XXXQXXXX
XQXXXXXX
XXXQXXXX
XXXXXQXX
XXXXXXXQ
XXQXXXXX
QXXXXXXX
XXXXXXQX
XXXXQXXX
XXQXXXXX
QXXXXXXX
XXXXXXQX
XXXXQXXX
XXXXXXXQ
XQXXXXXX
XXXQXXXX
XXXXXQXX
XXXQXXXX
QXXXXXXX
XXXXQXXX
XXXXXXXQ
XQXXXXXX
XXXXXXQX
XXQXXXXX
XXXXXQXX
XXXXQXXX
QXXXXXXX
XXXQXXXX
XXXXXQXX
XXXXXXXQ
XQXXXXXX
XXXXXXQX
XXQXXXXX
XXXXXQXX
QXXXXXXX
XXXXQXXX
XQXXXXXX
XXXXXXXQ
XXQXXXXX
XXXXXXQX
XXXQXXXX
XXXXXXQX
QXXXXXXX
XXQXXXXX
XXXXXXXQ
XXXXXQXX
XXXQXXXX
XQXXXXXX
XXXXQXXX
XXXXXXXQ
XQXXXXXX
XXXQXXXX
QXXXXXXX
XXXXXXQX
XXXXQXXX
XXQXXXXX
XXXXXQXX