这是一道深搜题目!问题的关键是在剪枝。
下面我们对问题进行分析:
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<iostream>
#include<cstring>
#include<cmath>
#include<stdio.h>
using namespace std;
int vis[3][50], P[15];//三个方向 ↖↑↗在此三个方向都不能有皇后
int n, sum;
void DFS(int row);
int main()
{
for(n = 1; n <= 10; n++) //先打表不然会超时的
{
memset(vis,0,sizeof(vis));
sum = 0;
DFS(1);
P[n] = sum;
}
while(scanf("%d",&n), n)
{
printf("%d\n",P[n]);
}
return 0;
}
void DFS(int row)//每次都下一行,不用担心行问题
{
int i;
if(row == n + 1)//已经够n行了
{
sum ++;
return ;
}
for(i = 1; i <= n; i++)
{
if(vis[0][row-i+n] == 0 && vis[1][i] == 0 && vis[2][row+i] == 0)
{//不会回溯的同学要好好看看学习学习
vis[0][row-i+n] = vis[1][i] = vis[2][row+i] = 1;//变值
DFS(row + 1);//深搜
vis[0][row-i+n] = vis[1][i] = vis[2][row+i] = 0;//回溯
}
}
}
https://www.cnblogs.com/chenchengxun/p/3759278.html
小白的代码记录
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdio>
#include <deque>
#include <vector>
using namespace std;
int vix[15];
int viy[15];
int dui1;
int dui2;
int sum;
int num;
bool judge(int x,int y);
void dfs(int x,int y);
void in(int x,int y)
{
vix[x]=1;
viy[y]=1;
if( x==y )
{
dui1=1;
}
if(x+y==num+1)
{
dui2=1;
}
}
void on(int x,int y)
{
vix[x]=0;
viy[y]=0;
if( x==y )
{
dui1=0;
}
if(x+y==num+1)
{
dui2=0;
}
}
int main()
{
while(cin>>num)
{
if(num==0)
break;
if(num==1)
{
cout<<"1"<<endl;
continue;
}
if(num==2)
{
cout<<"0"<<endl;
continue;
}
sum=dui1=dui2=0;
memset(vix,0,sizeof(vix));
memset(viy,0,sizeof(viy));
for(int i=1; i<=num; i++)
{
memset(vix,0,sizeof(vix));
memset(viy,0,sizeof(viy));
dui1=dui2=0;
in(1,i);
dfs(1,i);
}
cout<<sum<<endl;
}
return 0;
}
void dfs(int x,int y)
{
cout<<x<<" "<<y<<endl;
if( x==num )
{
sum++;
cout<<sum<<endl;
return;
}
for(int i=1; i<=num; i++)
{
if(judge(x+1,i) && x+1<=num)
{
in(x+1,i);
dfs(x+1,i);
on(x+1,i);
}
}
return;
}
bool judge(int x,int y)
{
if(vix[x]==1)
{
return false;
}
if(viy[y]==1)
{
return false;
}
if(x==y && dui1==1)
{
return false;
}
if(x+y==num+1 && dui2==1)
{
return false;
}
else
return true;
}