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 }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM