在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
题解:
- 首先要知道必须放满n个皇后。
- 先做一个check检查函数判断这点是否可以放一个皇后。
- 然后做一个dfs从起始状态(0,0)开始遍历判断。
- 这里要注意需要回溯,回溯就是说在调用dfs前判断(使用check函数发现可以放置一个皇后)后对一些已经做标记的位置(为了记忆化处理),在调用完dfs后要把做的标记改为原来的值。
- 这里我用flag对皇后所处的斜对角线进行标记,随着dfs调用的深入flag就应该与之前的值不一样,所以用flag++是一个比较不错的处理方式;记住一定要回溯。
- 到满足条件后(已经放置了n个皇后)进行return继续算后面还没遍历到的数据。
- 最后一点就是要用打表的方式提前计算出答案放入表里,当输入数据的时候直接从表里输出答案。
#include<iostream>
#include<cstring>
using namespace std;
int qipan[11][11];
int n,ans,flag;
int X[11],Y[11],A[11];
int check(int x,int y)
{
if(X[x]==0&&Y[y]==0&&qipan[x][y]==0)
{
if(y+1<n)
{
if(x-1>=0&&x+1<n)
{
if(qipan[x-1][y-1]!=1&&qipan[x-1][y+1]!=1&&qipan[x+1][y-1]!=1&&qipan[x+1][y+1]!=1)
return 1;
}
if(x-1<0)
{
if(qipan[x+1][y-1]!=1&&qipan[x+1][y+1]!=1)
return 1;
}
if(x+1==n)
{
if(qipan[x-1][y-1]!=1&&qipan[x-1][y+1]!=1)
return 1;
}
}
else if(y+1==n)
{
if(qipan[x-1][y-1]!=1&&qipan[x+1][y-1]!=1)
return 1;
}
}
return 0;
}
void dfs(int x)
{
flag++;
if(x==n)
{
ans++;
flag--;
return;
}
else for(int i=0;i<n;i++)
{
if(qipan[x][i]==2)continue;
if(check(x,i))
{
X[x]=1;
Y[i]=1;
qipan[x][i]=1;
for(int s=x,t=i;s<n&&t<n;s++,t++)if(qipan[s][t]==0)qipan[s][t]=flag;
for(int s=x,t=i;s>=0&&t>=0;s--,t--)if(qipan[s][t]==0)qipan[s][t]=flag;
for(int s=x,t=i;s<n&&t>=0;s++,t--)if(qipan[s][t]==0)qipan[s][t]=flag;
for(int s=x,t=i;s>=0&&t<n;s--,t++)if(qipan[s][t]==0)qipan[s][t]=flag;
dfs(x+1);
for(int s=x,t=i;s<n&&t<n;s++,t++)if(qipan[s][t]==flag)qipan[s][t]=0;
for(int s=x,t=i;s>=0&&t>=0;s--,t--)if(qipan[s][t]==flag)qipan[s][t]=0;
for(int s=x,t=i;s<n&&t>=0;s++,t--)if(qipan[s][t]==flag)qipan[s][t]=0;
for(int s=x,t=i;s>=0&&t<n;s--,t++)if(qipan[s][t]==flag)qipan[s][t]=0;
X[x]=0;
Y[i]=0;
qipan[x][i]=0;
}
}
flag--;
}
int main()
{
memset(A,0,sizeof(A));
A[1]=1;
for(n=2;n<=10;n++)
{
ans=0;
flag=2;
memset(qipan,0,sizeof(qipan));
memset(X,0,sizeof(X));
memset(Y,0,sizeof(Y));
dfs(0);
A[n]=ans;
}
while(cin>>n&&n)cout<<A[n]<<endl;
return 0;
}