暴力搜索,只要把握住几个地方就行了 :
1. 我们可以按照行来放置,因为任意两个棋子不能同行,所以对于每一行,要么放,要么不放。
2.我们可以用一个数组记录每一列在此之前有没有棋子,其实就是一个更简单的八皇后问题。
这样已经足够通过本题的数据了,但是我们还可以添加一个剪枝:如果当前棋子数+之后的行数 < k ,那么之后无论怎么放置都无法达到要求,应当剪枝。
细节参见代码:
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int INF = 1000000000;
const int maxn = 10 + 5;
int n,ans,k,vis[maxn];
char s[maxn][maxn];
void dfs(int r, int d) {
if(d == k) { ans++; return ; }
if(r == n+1) return ;
if(n - r + 1 + d < k) return ;
for(int j=1;j<=n;j++) {
if(s[r][j] == '#' && !vis[j]) {
vis[j] = 1;
dfs(r+1,d+1);
vis[j] = 0;
}
}
dfs(r+1,d);
}
int main() {
while(~scanf("%d%d",&n,&k)) {
if(n < 0 && k < 0) return 0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
ans = 0;
dfs(1,0);
printf("%d\n",ans);
}
return 0;
}