N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 39981 Accepted Submission(s): 16922
Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
题解:开始只知道要递归回溯,DFS;于是就采用直接暴搜,结果TLE,在看了大佬的代码后才知道要进行优化,于是代码如下:
TLE代码:
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
int a[25]; //每一行对应的皇后的位置
int t,sum;
bool vis(int x,int y) //判断是否可以放皇后
{
int j=1;
while(j<x)
{
if((a[j]==y)||(fabs(x-j)==fabs(a[j]-y)))
return false;
j++;
}
return true;
}
void place(int x)
{
if(x>t)
sum++; //如果已经摆放完毕,则数目加一
else
{
for(int y=1;y<=t;y++)
{
if(vis(x,y))
{
a[x]=y;
place(x+1); //递归回溯
}
}
}
}
int main()
{
while(~scanf("%d",&t))
{
sum=0;
if(t==0)
break;
place(1);
printf("%d\n",sum);
}
return 0;
}
AC代码:
#include<cstdio>
#include<cstring>
int n,numS[20]; //n表示几皇后问题,numS[20]表示每个n所对应的皇后问题数目
int num; //每个皇后问题对应的数目
int l[40],r[40],row[40]; //l表示左斜线,r表示右斜线,row表示每一列
void DFS(int x,int n)
{
if(x>n)
num++; //如果已经摆放完毕,则数目加一
else
{
for(int i=1;i<=n;i++)
{
if(l[x-i+n]==0&&r[x+i]==0&&row[i]==0)
{
l[x-i+n]=1;
r[x+i]=1;
row[i]=1;
DFS(x+1,n);
l[x-i+n]=0;
r[x+i]=0;
row[i]=0;
}
}
}
}
int main()
{
num=0;
for(int i=1;i<=10;i++) //开始就计算出每个n所对应的数目
{
num=0;
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
memset(row,0,sizeof(row));
DFS(1,i);
numS[i]=num;
}
while(~scanf("%d",&n))
{
if(n==0)
break;
else
printf("%d\n",numS[n]);
}
return 0;
}
tip:左右斜线参考博客:https://blog.csdn.net/you_will_know_me/article/details/78419088