HDU 2553 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

将此表列出我们就应该知道在(↗)方向上的数据的行和列的特点了,及   在 (↗)方向上  列 + 行 的和是相等的。

知道数据怎么处理就可以解决问题了。

下面附上参考代码:

 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)