【題目描述】
在一個給定形狀的棋盤(形狀可能是不規則的)上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列,請編程求解對於給定形狀和大小的棋盤,擺放 k 個棋子的所有可行的擺放方案 C。
【輸入】
輸入含有多組測試數據。
每組數據的第一行是兩個正整數n,k,用一個空格隔開,表示了將在一個n×n的矩陣內描述棋盤,以及擺放棋子的數目。(n≤8,k≤n)
當爲−1−1時表示輸入結束。
隨後的n行描述了棋盤的形狀:每行有n個字符,其中 # 表示棋盤區域,. 表示空白區域(數據保證不出現多餘的空白行或者空白列)。
【輸出】
對於每一組數據,給出一行輸出,輸出擺放的方案數目CC(數據保證C<2的31次方)。
【輸入樣例】
2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1
【輸出樣例】
2
1
本題與八皇后類似,但有所區別的就是八皇后要放八個皇后,而這題則是所放的棋子數量是不一定的,即k<=n;所以會存在dfs搜一次n行就有很多種方案,這就要求我們要把n行搜到底(一定要枚舉當前行後的每一行)。
#include<bits/stdc++.h>
using namespace std;
char a[9][9];
int n, k, l[9];
long long ans;
void dfs(int p, int cnt){//p:當前行 cnt:當前已經放的棋子數
if(cnt == k){
++ans;
return ;
}
for(int i=p; i<n; i++){//因爲k<=n,每行都放的話,是搜不到底的,所以一定要枚舉當前行之後的每一行
for(int j=0; j<n; j++){
if(a[i][j] == '#' && (!l[j]) ){
l[j] = 1;
dfs(i+1, cnt+1);//注意是i+1, 我因爲寫成了p+1,導致wa了好幾次
l[j] = 0;
}
}
}
}
int main(){
while(cin >> n >> k && n != -1 && k != -1){
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
cin >> a[i][j];
memset(l, 0, sizeof(l));
ans = 0;
dfs(0, 0);
cout << ans << endl;
}
return 0;
}