题目链接
这是一道深度搜索题,题目如下:
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input1
8
5
0
Sample Output1
92
10
这个题的大致题意是将n个棋子放在n×n的棋盘上,使n个棋子不同行不同列并且不同对角线共有多少种情况。
为了满足题意n个棋子必须在不同行,我们先将确定第一个棋子的位置,然后再从第二个棋子开始搜索,这个题我们需要标记列是否被占和左对角线是否被占和右对角线是否被占,所有的点都可以用坐标(x,y),来确定,而在同一个左对角线的点他们的x+y相同,在同一个右对角线的点他们的x-y相同,因此我们可以发现利用这个规律,对他们进行标记,写一个函数去判断这个点能不能放棋子,如果这个列/左对角线/右对角线已经访问过了则不能放在这。
这个题要注意在输入之前将1-10的结果提前存储好,也就是打表,这样才不会超时。
这里通过x+y-1将左对角线的序号分别标为1——2n-1,通过x-y+n将右对角线的序号分别标为1——2n-1,有兴趣的可以动笔在纸上试一下,这样更方便它们作为下标。
代码如下:
#include<iostream>
using namespace std;
int icount;
int n;
int bookh[11];
int zxie[25];
int yxie[25];
int judge(int x,int y)
{
if(bookh[y]==0&&zxie[x+y-1]==0&&yxie[x-y+n]==0)
return 1;
else
return 0;
}
void dfs(int line)
{
if(line==n+1)//搜索到n+1行时就说明棋盘确定了,情况加一
{
icount++;
return;
}
for(int i=1;i<=n;i++)//确定此行的棋子在第i列
{
if(judge(line,i))
{
bookh[i]=1;
zxie[line+i-1]=1;
yxie[line-i+n]=1;
dfs(line+1);
bookh[i]=0;
zxie[line+i-1]=0;
yxie[line-i+n]=0;
}
}
}
int main()
{
int end[11];
for(n=1;n<=10;n++)
{
icount=0;
for(int i=1;i<=n;i++)//确定第一行的在第i列
{
bookh[i]=1;//标记列被占
zxie[i]=1;//标记左斜对角线被占
yxie[1-i+n]=1;//标记右边斜对角线被占
dfs(2);//第一行已经确定了,要从第二行搜索
bookh[i]=0;
zxie[i]=0;
yxie[1-i+n]=0;
}
end[n]=icount;//打表
}
while(cin>>n&&n!=0)
{
cout<<end[n]<<endl;
}
return 0;
}