这是一道深搜题目!问题的关键是在剪枝。
下面我们对问题进行分析:
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
将此表列出我们就应该知道在()方向上的数据的行和列的特点了,及 在 ()方向上 列 + 行 的和是相等的。
知道数据怎么处理就可以解决问题了。
下面附上参考代码:
1 #include<iostream>
2 #include<cstring>
3 #include<cmath>
4 using namespace std;
5 int vis[3][50], P[15];//三个方向 ↑在此三个方向都不能有皇后
6 int n, sum;
7
8 void DFS(int row);
9
10 int main()
11 {
12 for(n = 1; n <= 10; n++)//先打表不然会超时的
13 {
14 memset(vis,0,sizeof(vis));
15 sum = 0;
16 DFS(1);
17 P[n] = sum;
18 }
19 while(scanf("%d",&n), n)
20 {
21 printf("%d\n",P[n]);
22 }
23 return 0;
24 }
25
26 void DFS(int row)
27 {
28 int i;
29 if(row == n + 1)//已经够n行了
30 {
31 sum ++;
32 return ;
33 }
34 for(i = 1; i <= n; i++)
35 {
36 if(vis[0][row-i+n] == 0 && vis[1][i] == 0 && vis[2][row+i] == 0)
37 {//不会回溯的同学要好好看看学习学习
38 vis[0][row-i+n] = vis[1][i] = vis[2][row+i] = 1;//变值
39 DFS(row + 1);//深搜
40 vis[0][row-i+n] = vis[1][i] = vis[2][row+i] = 0;//回溯
41 }
42 }
43 }
HDU 2553 N皇后问题(详细题解),布布扣,bubuko.com
时间: 2024-08-03 15:29:37