POJ-1321棋盤問題
阿新 • • 發佈:2018-11-25
棋盤問題
輸入含有多組測試資料。
每組資料的第一行是兩個正整數,n k,用一個空格隔開,表示了將在一個n*n的矩陣內描述棋盤,以及擺放棋子的數目。 n <= 8 , k <= n
當為-1 -1時表示輸入結束。
隨後的n行描述了棋盤的形狀:每行有n個字元,其中 # 表示棋盤區域, . 表示空白區域(資料保證不出現多餘的空白行或者空白列)。
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 62010 | Accepted: 29682 |
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
題意:輸入兩個整數n,k,輸入-1,-1時表示輸入結束,n代表n*n的棋盤,k代表目標放棋子的數目,棋盤的形狀不確定,但是#表示可以放,. 表示不可以放,問放k個棋子一共有多少种放法。
注意:判斷是否滿足條件和判斷是否越界的先後順序;
#include<iostream> #include<cstring> using namespace std; int n,k,cnt,t; int vis[8]; char maze[8][8]; void dfs(int x) { //注意這兩個if,順序不能顛倒,否則結果比實際滿足要求的數量少1; /*原因:程式執行到這裡時,已經從上一層滿足條件的情況跳到了下一層了, 所以此時的t是上一層滿足條件的t的數量,而x是目前這一層的情況,還沒有判斷x是否越界和 判斷是否可以放棋子,所以,這個t要優先判斷是否滿足了題意,然否再判斷x是否越界; */ if(t==k) { cnt++; return ; } if(x>=n) return ; for(int j=0;j<n;j++) { if(maze[x][j]=='#'&&!vis[j])//滿足要求的條件是:這個位置是#,這個位置沒有被標記過; { vis[j]=1;//對當前符合要求的這層的這一列標記; t++; //放上一個棋子,棋子數量+1; dfs(x+1); vis[j]=0;//返回到了上一層,對這一層解除標記; t--; //因為返回到了上一層,所以要減去這一層放上的棋子; } } dfs(x+1);//這一層沒有符合要求的,只能跳過這層了,所以,層數增加,棋子數量不增加; } int main() { while(cin>>n>>k&&n<=8&&k<=n&&n!=-1&&k!=-1) { cnt=0;//記錄滿足情況的數目; t=0;//記錄放入棋子的個數; for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin>>maze[i][j]; memset(vis,0,sizeof(vis));//也可以這樣寫:memset(vis,0,n*n); dfs(0);//從第一層開始搜尋第一個適合放棋子的地方; cout<<cnt<<endl; } return 0; } /*dfs的另一種寫法:每次傳遞兩個引數; 注意把main()中的dfs改為dfs(0,0); void dfs(int x,int t) { if(t==k) { cnt++; return ; } if(x>=n) return ; for(int j=0;j<n;j++) { if(maze[x][j]=='#'&&!vis[j]) { vis[j]=1; dfs(x+1,++t);//注意t,一定要寫成++t,t++和t+1都不對,因為我們的目的是讓t在呼叫dfs之前就增加1,如果不這樣寫達不到目標效果; vis[j]=0; t--; } } dfs(x+1,t); } */