POJ 1321 棋盤問題(DFS)

原題

棋盤問題

Time Limit: 1 Sec Memory Limit: 32 MB

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

2
1

涉及知識及算法


首先我們可以明確這是一個深度搜索的題目,與八皇后問題相似。我們建立一個函數DFS用來累計可行的方案數,我們走過一列我們就把它標記下來下次的時候就不可以再擺放在這一列(因爲題目要求不可以將棋子擺放在同一行和同一列)

然後就從下一行開始尋找可行的地方,直到我們擺放的棋子數與我們被要求擺放的棋子數相同時,我們就將方案數進行一次++,然後在進行遞歸下去。

代碼

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
 
int n,k,ans;
//棋盤
char Map[12][12];
int vis[12];
int DFS(int i,int cur)
{
    //如果可以擺完k個棋子,方案數加一併返回
    if(cur>=k)
    {
        ans++;
        return 0;
    }
    //從當前行開始,並在其中循環遍歷以實現所有
    // 可能情況的組合·
    for(int x=i;x<n;x++)
    {
        for(int y=0;y<n;y++)
        {
            if(!vis[y]&&Map[x][y]=='#')
            {
                vis[y]=1;
                //在下一列擺放下一個
                DFS(x+1,cur+1);
                //一個方案模擬後就還原
                vis[y]=0;
            }
        }
    }
    return 0;
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&k)&&n!=-1)
    {
        ans=0;
        memset(Map,0,sizeof(Map));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            scanf("%s",Map[i]);
        }
        DFS(0,0);
        printf("%d\n",ans);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1310
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1504 kb
****************************************************************/
文章轉載自博客園博主心向晴,鏈接http://www.cnblogs.com/xinxiangqing/p/4692994.html,向他/她表示感謝




發佈了25 篇原創文章 · 獲贊 9 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章