N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5654 Accepted Submission(s): 2555
你的任务是,对于给定的N,求出有多少种合法的放置方法。
这是一道深搜题目!问题的关键是在剪枝。
下面我们对问题进行分析:
1.一行只能放一个皇后,所以我们一旦确定此处可以放皇后,那么该行就只能放一个皇后,下面的就不要再搜了。
2.每一列只能放一个皇后,所以我们下次搜索就不要再搜已经放过的皇后了。
3.斜的45°线也只能放一个。
综上如何才能最快速的确定一列和45°是否用过这个是个关键步骤,一旦此步骤确定我们就可以很快的进行搜索了。
我们用三个数组来保存他的每一个状态及(三个方向 ↖ ↑ ↗)
但是如果我们保存↑(每一列方向上的皇后)是非常容易保存的 但是保存( 这两个方向上的状态就不容易了↖ ↗)
再分析,在这个(↖)方向上的数据的行和列有什么特点
0 1 2 3 4
-1 0 1 2 3
-2 -1 0 1 2
-3 -2 -1 0 1
-4 -3 -2 -1 0
将此表列出我们就应该知道在(↖)方向上的数据的行和列的特点了,及 在 (↖)方向上 列 - 行 的差是相等的。
假如我们用数组保存负数肯定是不行的, 所以我们要加上 n,让他变为非负.
再分析,在这个( ↗)方向上的数据的行和列有什么特点
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
将此表列出我们就应该知道在(↗)方向上的数据的行和列的特点了,及 在 (↗)方向上 列 + 行 的和是相等的。
知道数据怎么处理就可以解决问题了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 25;
int ans[maxn], n, sum;
bool vis[3][maxn];
void dfs(int cur)
{
if(cur == n+1) { sum++; return ; }
for(int i = 1; i <= n; i++)
{
if(!vis[0][i] && !vis[1][i-cur+n] && !vis[2][i+cur])
{
vis[0][i] = vis[1][i-cur+n] = vis[2][i+cur] = 1;
dfs(cur+1);
vis[0][i] = vis[1][i-cur+n] = vis[2][i+cur] = 0;
}
}
}
int main(void)
{
for(n = 1; n <= 10; n++)
{
memset(vis, 0, sizeof(vis));
sum = 0;
dfs(1);
ans[n] = sum;
}
while(cin >> n, n)
printf("%d\n", ans[n]);
return 0;
}
这道题最直接的思路就是枚举 暴力解决,但是显然是不行的。
所以只能用回溯。 基本思路 ,一行一行的放 皇后, 然后再递归判断是否与之前已放好的皇后有冲突,一旦有冲突,则不需要继续下一行的搜索,直接返回(省去不必要的枚举)。
另外关于这题,还有一点,我第一次交的时候TLE了,说明测试数据特别多。所以得先预处理(这个亏吃了很多次了,牢记牢记).
//八皇后问题 回溯法
#include<stdio.h>
int tot=0,row,line[10],n;
int main()
{
void search(int );
int a[11];
for(n=1;n<=10;n++) //之前就是没有这一步预处理,所以TLE了 TT
{
tot=0;
search(0);
a[n]=tot;
}
while(scanf("%d",&n)!=EOF&&n)
printf("%d\n",a[n]);
return 0;
}
void search(int row) //递归搜索可行解
{
int i,j;
if(row==n) tot++; //当row=n时,说明每一行的皇后都不冲突,即为可行解
else
for(i=0;i<n;i++)
{
int ok=1;
line[row]=i; //尝试把第row行的皇后放在i列上
for(j=0;j<row;j++) //检验是否与前面已放好的皇后冲突
{
if(line[row]==line[j]||line[row]-row==line[j]-j||line[row]+row==line[j]+j)
{
ok=0;
break; //,跳出最内层循环如果冲突,停止搜索,返回上一级递归回溯。回溯法高效的关键。
}
}
if(ok)
search(row+1);
}
}