POJ 1321 - 棋盤問題 - [經典DFS]

題目連接:http://poj.org/problem?id=1321編程

Time Limit: 1000MS Memory Limit: 10000K函數

Description測試

在一個給定形狀的棋盤(形狀多是不規則的)上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列,請編程求解對於給定形狀和大小的棋盤,擺放k個棋子的全部可行的擺放方案C。

Inputspa

輸入含有多組測試數據。 
每組數據的第一行是兩個正整數,n k,用一個空格隔開,表示了將在一個n*n的矩陣內描述棋盤,以及擺放棋子的數目。 n <= 8 , k <= n 
當爲-1 -1時表示輸入結束。 
隨後的n行描述了棋盤的形狀:每行有n個字符,其中 # 表示棋盤區域, . 表示空白區域(數據保證不出現多餘的空白行或者空白列)。 

Outputcode

對於每一組數據,給出一行輸出,輸出擺放的方案數目C (數據保證C<2^31)。

Sample Inputblog

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

Sample Outputip

2
1

 

能夠說是很是經典的一道DFS題目了,不說有多難,可是能夠很好地體現出DFS的思想。get

 

對於一個n*n的棋盤,咱們考慮按行進行DFS,一行一行往下推動就相似於DFS一層一層往下搜索。string

對於函數dfs(int row,int num),row表示當前進行到哪一行,num表明到目前爲止,棋盤上已經放了多少棋子了。it

那麼,在dfs()這個函數中,顯然要對row這行上的每一格進行一次遍歷(一次for循環);

遍歷的過程當中,遇到能放棋子的格子(兩個要求:①這一格確實是屬於棋盤的 map[i][j]='#' ;  ②這一列上,上面那幾行沒有放過棋子 vis[col]==0 ),那就無論了,先放上去再說;

那麼咱們放了一顆棋子以後,這行就不能再放了,那就往下走一行dfs(row+1,num+1);

那麼咱們dfs(row+1,num+1)這個作完了以後呢?

顯然,咱們又不是必定要往這個格子上放旗子,棋盤這麼大我想去看看,因此咱們要把以前放下的那顆棋子拿起來,繼續在row這行上繼續遍歷,尋找下一個能放棋子的格子;

 

最後我若是把這一行所有遍歷完了呢?咱們是否是非得往這行上放棋子?

固然不是啦

若是棋子少,這行不放也是能夠的呀,因此在一次for循環結束以後,咱們也要往下一行走,即dfs(row+1,num)。

 

這就是大致上的DFS思路啦,更多細節請詳見代碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 char map[11][11];
 4 int n,k,ans;
 5 bool colvis[11];
 6 void dfs(int row,int num)
 7 {
 8     if(num==k)//所有chess都已經放完啦! 
 9     {
10         ans++;//方案數+1
11         return;
12     }
13     if(row>n) return;
14     for(int col=1;col<=n;col++)
15     {
16         if(map[row][col]=='#' && !colvis[col])
17         {
18             colvis[col]=1;
19             dfs(row+1,num+1);
20             colvis[col]=0;
21         }
22     }
23     dfs(row+1,num);
24 }
25 int main()
26 {
27     while(scanf("%d%d",&n,&k) && n!=-1)
28     {
29         memset(colvis,0,sizeof(colvis));
30         memset(map,0,sizeof(map));
31         for(int i=1;i<=n;i++) scanf("%s",map[i]+1);
32         ans=0;
33         dfs(1,0);
34         printf("%d\n",ans);
35     }
36 }

 潑婦愛科特!!!

相關文章
相關標籤/搜索