今天学习了第9章的八皇后问题,Python简洁的语法令我叹服。现总结如下:
Python实现程序如下:
def conflict(state,nextX):
nextY=len(state)
for i in range(nextY):
if abs(state[i]-nextX) in (0,nextY-i):
return True
return False
def queens(num=8,state=()):
for pos in range(num):
if not conflict(state,pos):
if len(state)==num-1:
yield (pos,)
else:
for result in queens(num,state+(pos,)):
yield(pos,)+result
def prettyprint(solution):
def line(pos,length=len(solution)):
return '. ' * (pos) + 'X ' + '. ' * (length-pos-1)
for pos in solution:
print line(pos)
相信最难理解的应该就是红色标注的那行了,代码含义是:如果下一个皇后和正在考虑的前一个皇后的水平距离为0(列相同)或者等于垂直距离(在一条对角线上)就返回True,否则就返回False。百思不得其解,于是上网查询到一篇用C++实现的文章(网址:http://javayestome.iteye.com/blog/1060240),代码如下:
#include
#include
#include
using namespace std;
bool conflict(const vector&state,int nextX)
{
int nextY=state.size();
for(int i=0;i
{
if((abs(nextX-state[i])==0)||(abs(nextX-state[i])==(nextY-i)))
{
return true;
}
}
return false;
}
void queen(int num,vector& state)
{
for(int i=0;i
{
state.clear();
state.push_back(i);
int pos=0;
while(state.size()!=num)
{
if(conflict(state,pos))//冲突了
{
if(pos==num-1)//已经是最后一个位置
{
state.pop_back();
break;
}
pos++;//尝试下一个pos
continue;
}
else//没有冲突
{
state.push_back(pos);
pos=0;
}
}
if(state.size()==num)
return;
}
}
void print(int num,const vectorresult)
{
for(int i=0;i
{
for(int j=0;j
{
cout<<".";
}
cout<<"X";
for(int j=0;j
{
cout<<".";
}
cout<
}
}
int main()
{
vector
state;
queen(8,state);
print(8,state);
system("pause");
}
其中,红色标注代码即为Python版本的C++解释,为了更好的理解,做如下解释:
如上图所示,已经放置三个皇后,现在要在最后一行放置皇后,让我们看看上面的代码是如何工作的。
但是这个程序只能找到一种解决方案,希望找到全部的求解方案,并进行输出。经过搜索,网上有两种方案,第一种是多个for循环进行嵌套的方案,思想比较简单,下面介绍第二种方案(网址:http://blog.csdn.net/bytyp/article/details/4043326)。程序如下:
#include
#include
using namespace std;
class QueenChess
{
public:
QueenChess();
//构造函数
void Solve();
//求解八皇后问题,并给出放置成功的棋盘总个数
private:
string chessState[8];
//用于存放棋盘状态
int solves;
//八个皇后放置成功的棋盘解的总个数
bool SafeJudge(int row,int col) const; //判断位置(row,col)是否安全
void PlaceQueen(int row); //在第row行放置一个皇后
void DrawChess() const; //打印八个皇后放置成功的棋盘
};
QueenChess::QueenChess()
//构造函数,将棋盘初始化
{
solves=0;
int i=0;
for(;i<8;++i)
chessState[i]="--------";
}
void QueenChess::Solve()
//求解八皇后问题,并给出放置成功的棋盘总个数
{
PlaceQueen(0);
//从第0行开始放置皇后
cout<<"八皇后问题总共的解的个数是:"<
}
void QueenChess::PlaceQueen(int row)
//在第row行的各列放置皇后
{
for(int col=0;col<8;col++)
//穷尽第row行的所有列
{
if(SafeJudge(row,col))
{
chessState[row][col]='Q';
//位置(row,col)安全,则放一皇后
if(row<7)
//若还没有放到第八行,则尝试下一行
{
PlaceQueen(row+1);
}
else
//已经放置了八个皇后,打印出成功的棋盘,并将解数加1
{
solves++;
DrawChess();
}
}
chessState[row]="--------";
//不安全,将该处的皇后拿走,尝试下一列位置
}
}
bool QueenChess::SafeJudge(int row,int col) const
//判断是否(row,col)是安全位置
{
int qRow,qCol;
for(qRow=0;qRow
//检查前面各行,看与前面的皇后是否发生攻击
{
string rowState=chessState[qRow];
qCol=rowState.find("Q");
//寻找第qRow行放置皇后的列数
if(qRow==row||qCol==col||(qCol-qRow)==(col-row)||(qCol+qRow)==(col+row))
{//如果两个皇后在同一行、同一列或两条对角线上,则说明该位置不安全
return false;
}
}
return true;
}
void QueenChess::DrawChess() const
//打印成功的棋盘
{
int i,j;
cout<<"八皇后问题的第"<
cout<<" 0 1 2 3 4 5 6 7"<
for(i=0;i<8;++i)
{
cout<
for(j=0;j<8;++j)
cout<
cout<
}
//system("pause");
}
int main()
{
QueenChess chess;
chess.Solve();
system("pause");
return 0;
}