时限
1000毫秒
内存限制
32768 kB
在N * N的方格棋盘放置了Ñ个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
输入
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N = 0,表示结束。
产量
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
样本输入
1
8
5
0
样本输出
1
92
10
思路:为了不超时还得提前打表,DFS按行进行搜索,注意对于列,主对角线和副对角线的表示。
这道题一曲三折,先贴AC代码在分析:
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
int ans[10]={1,0,0,2,10,4,40,92,352,724};
int main()
{
int m;
while(~scanf("%d",&m)&&m)
{
cout<<ans[m-1]<<endl;
}
return 0;
}
第一发TLE,代码如下:
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 50;
int n,tot;
int vis[3][maxn];
void dfs(int cur)
{
if(cur==n)
{
tot++;
}
else{
for(int i=0;i<n;i++){
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){ //分别表示行,主对角线,副对角线
vis[0][i]=1;
vis[1][cur+i]=1;
vis[2][cur-i+n]=1;
dfs(cur+1);
vis[0][i]=0;
vis[1][cur+i]=0;
vis[2][cur-i+n]=0;
}
}
}
}
int main()
{
while(~scanf("%d",&n)&&n)
{
tot=0;
memset(vis,0,sizeof(vis));
dfs(0);
cout<<tot<<endl;
}
return 0;
}
觉得不打表真过不了于是想打表试试代码如下(果断AC了)!:
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 20;
int n,tot;
int vis[3][maxn];
void dfs(int cur)
{
if(cur==n+1)
{
tot++;
return ;
}
else{
for(int i=1;i<=n;i++){
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){ //分别表示行,主对角线,副对角线
vis[0][i]=1;
vis[1][cur+i]=1;
vis[2][cur-i+n]=1;
dfs(cur+1);
vis[0][i]=0;
vis[1][cur+i]=0;
vis[2][cur-i+n]=0;
}
}
}
}
int main()
{
int ans[11];
for(n=1;n<=10;n++) //为了不超时还得打表,真是无语
{
tot=0;
dfs(1);
ans[n]=tot;
}
int m;
while(~scanf("%d",&m)&&m)
{
cout<<ans[m]<<endl;
}
return 0;
}