数据比较小,怎么暴力都行。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 1<<8
#define maxm 8111111
int n, kk;
char mp[11][11];
long long dp[11][maxn]; //放到第i行 状态为j 已经放置k个棋子的种数
int board[11]; // 第i行的状态
int num[maxn], state[maxn], cnt;
int get (int x) { //x二进制1的个数
int ans = 0;
while (x) {
if (x&1)
ans++;
x >>= 1;
}
return ans;
}
bool ok (int x) {
if (x == 0)
return 1;
for (int i = 1; i < (1<<n); i <<= 1) {
if (x == i)
return 1;
}
return 0;
}
int main () {
//freopen ("in", "r", stdin);
for (int i = 0; i < maxn; i++) {
num[i] = get (i);
}
cnt = 0; state[++cnt] = 0;
for (int i = 0; i <= 7; i++) {
state[++cnt] = (1<<i);
}
while (scanf ("%d%d", &n, &kk) == 2) {
if (n == kk && n == -1)
break;
for (int i = 0; i < n; i++) {
scanf ("%s", &mp[i]);
board[i] = 0;
for (int j = 0; j < n; j++) {
board[i] = (board[i]<<1) + (mp[i][j] == '#' ? 0 : 1);
}
}
memset (dp, 0, sizeof dp);
for (int i = 1; i <= cnt && state[i] < (1<<n); i++) {
if (board[0]&state[i])
continue;
dp[0][state[i]] = 1;
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < (1<<n); j++) {
for (int y = 1; y <= cnt && state[y] < (1<<n); y++) {
int k = state[y];
if (j&k)
continue;
if (board[i]&k)
continue;
dp[i][k^j] += dp[i-1][j];
}
}
}
long long ans = 0;
for (int i = 0; i < (1<<n); i++) {
if (num[i] == kk)
ans += dp[n-1][i];
}
printf ("%lld\n", ans);
}
return 0;
}