C++老师布置了一道八皇后问题,自己做了几天:用一维数组映射成二维数组作为N*N棋盘,用堆栈实现,相当麻烦而且已经不打算考虑时间复杂度(因为实在是相当复杂了),而且由于是用四皇后做的例子,结果推广的时候不正确,原因应该是成功找到一个结果后完全清空堆栈,没有继续查找。我也不打算再改了,实在太麻烦。
做这个题目有个小地方要注意:某位置的斜线位置的表示方法是 abs(X[i]-X[k])==abs(i-k) 对角线检查(列与列之差,行与行之差绝对值相等则为同一斜线)
以下是我参考网上搜的代码http://www.cnblogs.com/three-zone/archive/2011/12/09/NPQ.html,但是它这个用的内存超过了数组下标的限制,而且没有释放使用的内存,当然这只是一些小毛病,我也只是做了一些小修改。
以下是代码:
///n_queens_problem.cpp
#include<iostream>
#include<cmath>
using namespace std;
bool place(int k,int *X)
{
int i;
i=0;
while(i<k) //只需检查k行之前的行,k行之后的行还没有放
{
if((X[i]==X[k])||(abs(X[i]-X[k])==abs(i-k))) //X[i]==X[k]表示列检查;abs(X[i]-X[k])==abs(i-k)表示对角线检查(列与列之差,行与行之差绝对值相等则为同一斜线)
return false;
i++;
}
return true;
}
/*k*/
int nQueens(int n,int* X)
{
int k,sum=0;
X[0]=-1;
k=0;
while(k>=0)
{
X[k]=X[k]+1; //即便已经找到合适的,X[k]依然加1继续看k行后面的数能否满足
while((X[k]<n)&&(!place(k, X))) //k行的第几列可以放置
X[k]=X[k]+1; //列数自加
if(X[k]<n) //x[k]<=n表示通过以上的检查后这一行如果能放,
if(k==n-1) //且这一行已经是最后一行,则输出
{
// for(int i=0;i<n;i++)
// cout<<X[i]<<" ";
// cout<<endl;
sum++;
}
else //不是最后一行,则进入下一行
{
k=k+1; //行数自加
X[k]=-1;
}
else //如果不能放,回到上一行
k=k-1;
}
//cout<<"解的总数为:"<<sum<<endl;
return sum;
}
int main()
{
cout<<"***********************\n"
<<"* n皇后问题 *\n"
<<"***********************\n";
cout<<"请输入皇后个数:";
int n;
cin>>n;
cout<<"问题的解决如下:\n";
int *Chess=new int[n];
n=nQueens(n,Chess);
cout<<"结果总数:"<<n<<"\n";
delete[] Chess;
return 0;
}
比起我写的要帅气的多,值得学习。
这种方法对于皇后数较大时速度很慢,queens=16时用了半个小时才出来,而位运算的办法只用了不到一分钟
他介绍的另一种方法我没有看完,是用位运算实现的,速度快,以后看。