【题目描述】
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放 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;
}