突破口:
N*N的棋盘放置N个皇后,因为皇后的特性,合法的放置方法中每行(每列)必定有一个皇后,因此我们可以先搜索第1行可以放置的位置,再逐步搜索第2行,直到第N行。而不用去穷举第一个棋子在棋盘中的位置,这样做是会超时,而且会重复运算的。
代码如下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
char s[11][11]; //模拟棋盘,s[i][j]='0'说明这里可以放置一个皇后,否则则不行
int N,cnt;
void func(int x,int y,int flag) //将皇后所在的行,列,主副对角线全部进行处理,使它们不能够被放置皇后或者恢复原样
{
int i,j;
for(i=1;i<=N;i++)
{
s[i][y]+=flag;
s[x][i]+=flag;
}
for(i=x+1,j=y+1;i<=N&&j<=N;i++,j++)
s[i][j]+=flag;
for(i=x-1,j=y-1;i>=1&&j>=1;i--,j--)
s[i][j]+=flag;
for(i=x+1,j=y-1;i<=N&&j>=1;i++,j--)
s[i][j]+=flag;
for(i=x-1,j=y+1;i>=1&&j<=N;i--,j++)
s[i][j]+=flag;
}
void place(int row,int num) //搜索,row记录当前所在行,num记录当前下的皇后个数
{
if(num==N) //num=N,cnt++,就可以结束了
{
cnt++;
return;
}
if(row>N) //不可越界
return;
int i,j;
for(i=1;i<=N;i++)
{
if(s[row][i]=='0')
{
func(row,i,1); //处理
s[row][i]='Q';
place(row+1,num+1);
func(row,i,-1); //恢复
s[row][i]='0';
}
}
}
int main()
{
int ans[11]={0,1,0,0}; //1~3的情况很容易分析出来
int i,j;
for(i=0;i<=10;i++)
for(j=0;j<=10;j++)
s[i][j]='0';
for(i=4;i<=10;i++)
{
N=i;cnt=0;
place(1,0);
ans[i]=cnt;//cout<<ans[i]<<endl;
}
while((cin>>N)&&N)
cout<<ans[N]<<endl;
return 0;
}