问题描述:在N*N的棋盘上按照以下规则摆放N个皇后:
1.任何两个皇后不能同行。
2任何两个皇后不能同列。
3.任何两个皇后不能在同一条斜线上。
求最终解的个数?
解题思路:这是一道经典的回溯题,那么可以用DFS做,需要注意的是,在摆放当前行或当前列的皇后时,需要判断哪个位置能够摆放,所以要对每个位置进行判断,这样时间复杂度就很高了,所以可以用三个数组记录一下当前位置的摆放情况,在下一次摆放皇后的时候只需要遍历三个位置能否摆放即可。当然这道题的数据很水,不优化也能过。。。优不优化看你心情咯~~
最后需要注意的是,这道题的样例数可能很大,最后先打表再输出答案,否则会TLE哦!!!
代码实现:
1.二维数组
#include<stdio.h>
#include<string.h>
int vis[15][15];
int n,sum;
void dfs(int x,int y)
{
int i,j;
if(x==n)
{
sum++;
return;
}
for(i = x+1; i <= n; i++)
{
vis[i][y]++;
for(j = 1; j <= n; j++)
{
if(i+j==x+y||j-i==y-x)
{
vis[i][j]++;
}
}
}
for(i = 1; i <= n; i++)
{
if(!vis[x+1][i])
{
vis[x+1][i]++;
dfs(x+1,i);
vis[x+1][i]--;
}
}
for(i = x+1; i <= n; i++)
{
vis[i][y]--;
for(j = 1; j <= n; j++)
{
if(i+j==x+y||j-i==y-x)
{
vis[i][j]--;
}
}
}
return;
}
int main()
{
int num[15];
int i;
for(n = 1; n <= 10; n++)
{
sum = 0;
if(n==1) sum = 1;
else
{
for(i = 1; i <= n/2; i++)
{
memset(vis,0,sizeof(vis));
vis[1][i] = 1;
dfs(1,i);
}
sum *= 2;
if(n%2)
{
memset(vis,0,sizeof(vis));
vis[1][n/2+1] = 1;
dfs(1,n/2+1);
}
}
num[n] = sum;
}
while(scanf("%d",&n) != EOF && n)
{
printf("%d\n",num[n]);
}
}
2.记忆化搜索
#include <bits/stdc++.h>
using namespace std;
int a[15], check[3][30] = {0};
int ans[15], n, k, cnt;
void solve(int n)
{
if(k == n+1)
{
cnt++;
return;
}
for(int i = 1; i <= n; i++)
{
a[k] = i;
if((!check[0][i])&&(!check[1][k+i])&&(!check[2][k-i+n]))
{
check[0][i] = 1; check[1][k+i] = 1; check[2][k-i+n] = 1;
k++;
solve(n);
k--;
check[0][i] = 0; check[1][k+i] = 0; check[2][k-i+n] = 0;
}
}
}
int main()
{
for(int i = 1; i <= 10; i++)
{
cnt = 0;
k = 1;
solve(i);
ans[i] = cnt;
}
while(cin >> n && n)
{
cout << ans[n] << endl;
}
}