1. 程式人生 > >簡單搜尋專題(poj1321 )

簡單搜尋專題(poj1321 )

 

poj1321-棋盤問題

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 70333   Accepted: 33302

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

2
1

Source

 

 

 ‘#’處是可以放棋子的位置,迴圈中列舉一行中每一列放棋子的方案,可行的方案(達到要求:每行每列都只有一個棋子,剛好把所給的棋子用完)則ans++,具體解釋看程式碼。

這位博主的部落格連結的解釋寫的很明白,我也放上來。

這道題目類似N皇后問題,與之不同的是每一行不一定有棋盤,所以dfs裡要注意不一定是當前行。
思路很簡單,只需從第一行第一個開始搜尋,如果該位置該列沒被標記且為棋盤,那麼在這裡放上棋子,並標記,因為每行每列不能衝突,所以搜尋下一行,比並且棋子數加1。每次搜尋之前先要判斷是否棋子已經用完,如果用完,記錄方案數加1,然後直接返回。直到所有搜尋全部完成,此時已得到全部方案數。
此題還需注意標記陣列僅僅標記某一列上是否有棋子,因為每次遞迴下一行,所以每一行不會有衝突,只需判斷這一列上是否有其他棋子。還要注意修改標記後遞歸回來要及時復原。
 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <map>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5;
char mp[15][15];
int vis[maxn];
int n,k,ans;
void dfs(int x,int q)//x:行數  c: 所用棋子數
{
    if(q == k)//找到了一種方案,停止搜尋
    {
        ans ++;
        return;
    }
    for(int i = x;i < n;i++)//繼續搜尋下面的行
    {
        for(int j = 0;j < n;j++)//遍歷各個行的每一列
        {
            if(mp[i][j] == '#' && !vis[j])//該處是棋盤且之前沒有被出現同列的標記過
            {
                vis[j] = 1;//標記這一行的該列已經出現過
                dfs(i+1,q+1);//搜尋下一行
                vis[j] = 0;//下一行的每一列不受影響,把標記全部清空
            }
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&k) != EOF)
    {
        if(n == -1 && k == -1)
            break;
        ans = 0;
        for(int i = 0;i < n;i++)
        {
            scanf("%s",mp[i]);
        }
        dfs(0,0);
        cout<<ans<<endl;
    }
   
    return 0;
}