八皇后:西洋棋中的皇后可以直线前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则这八个皇后如何相安无事的放置在棋盘上,1970年与1971年, E.W.Dijkstra与N.Wirth曾经用这个问题来讲解程序设计的结构性编程技巧。
在8*8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上
解法:关于棋盘的问题,都可以用递回求解,然而如何减少递回的次数?在八个皇后的问题中,不必要所有的格子都检查过,例如若某列检查过(已被放置),该该列的其它格子就不用再检查了,这个方法称为剪支。显然,每一行可以而且必须放一个皇后,所以n皇后问题的解可以用一个n元向量X=(x1,x2,.....xn)表示,其中,1≤ i≤ n且1≤ xi≤ n,即第n个皇后放在第i行第xi列上。
由于两个皇后不能放在同一列上,所以,解向量X必须满足的约束条件为:
xi≠ xj;
若两个皇后的摆放位置分别是(i,xi)和(j,xj),在棋盘上斜率为-1的斜线上,满足条件i-j=xi-xj;在棋盘上斜率为1的斜线上,满足条件i+j=xi+xj;
综合两种情况,由于两个皇后不能位于同一斜线上,所以,
解向量X必须满足的约束条件为:
|i-xi|≠ |j-xj|
#include <iostream>
#include <string>
using namespace std;
int x[8];
bool place(int k)
{
int i;
for(i=1;i<k;i++)
if(x[k]==x[i] || abs(k-i)==abs(x[k]-x[i]))
return false;
return true;
}
void queue()
{
int i,k;
for(i=1;i<=8;i++)
x[i]=0;
k=1;
while (k>=1)
{
x[k]=x[k]+1; //在下一列放置第k个皇后
while(x[k]<=8&&!place(k))
x[k]=x[k]+1; //搜索下一列
if(x[k]<=8&&k==8)//得到一个输出
{
for(i=1;i<=8;i++)
cout<<x[i]<<" ";
cout<<endl; //若return则只求出其中一种解,若不return则可以继续回溯,求出全部的可能的解
}
else if (x[k]<=8 && k<8)
{
k++;
}
else
{
x[k]=0;
k--;
}
}
}
int main()
{
cout<<"皇后位置: "<<endl;
queue();
system("pause");
return 0;
}