1019. Separate the Animals (35)


时间限制



1000 ms



内存限制



65536 kB



代码长度限制



8000 B



判题程序



Standard



作者



LIU, Rujia


There are some animals in a zoo which can be described as a grid with N rows and M columns. Your task is to place some obstacles so that no pairs of animals can reach each other.

Two animals can reach each other if and only if their cells are 4-connected. For example, in Figure 1, the central blue cell can be reached by the four red cells, and cannot be reached by the other four white cells.




Figure 1


What is more, you must put obstacles in exactly K cells, which are 4-connected and form exactly H holes. Here a hole is defined as a 4-connected part with finitely many open cells while the zoo is placed in an infinite open grid. For example, there are 2 holes (the green and the yellow areas) in Figure 2.




Figure 2


For the following grid with two animals:




Figure 3


If K = 8 and H = 1, one way to separate them is the following:




Figure 4


Figure 5 is illegal because it contains no hole.




Figure 5


Figure 6 is also illegal because the obstacles are not 4-connected.




Figure 6


Given some animals, you are supposed to count the number of different solutions.

Input Specification:

Each input file contains one test case. For each case, the first line gives four integers: N, M, K, H (2 <= N, M <= 6; 1 <= K <= 12; 0 <= H <= 2). All the numbers are separated by spaces.

Then N lines follow, each contains M characters, which are either "." or "O", representing an open cell or an animal, respectively. There will be at least 2 animals.

Output Specification:

For each case, print a single line containing a single integer: the number of solutions.


Sample Input:


3 5 8 1 ...O. .O... .....


Sample Output:


8



#include<map> 
#include<set>
#include<ctime>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define ms(x,y) memset(x,y,sizeof(x))
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define loop(i,j,k) for (int i=j;i!=-1;i=k[i])
#define inone(x) scanf("%d",&x)
#define intwo(x,y) scanf("%d%d",&x,&y)
#define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define mp(i,j) make_pair(i,j)
#define ff first
#define ss second
typedef int LL;
typedef pair<LL, LL> pii;
const int low(int x) { return x&-x; }
const double eps = 1e-6;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 15;
int n, m, t, h;
int fa[N*N][N*N], ga[N*N][N*N], sa[N*N][N*N], a[N][N], ans, vis[N][N];
int ha[N*N][N*N], hole[N], b[N*N];
char s[N][N];
int dir[4][2] = { 0,1,0,-1,1,0,-1,0 };

int get(int fa[], int x) {
return fa[x] == x ? x : fa[x] = get(fa, fa[x]);
}

void dfs(int now, int cnt, int con) {
if (cnt > t) return;
if (con - 1 > t - cnt) return;
if (t - cnt > n*m - now + 1) return;
if (now > n * m) {
if (cnt < t || con != 1 || hole[now - 1] != h) return;
ans++;
return;
}

int x = (now - 1) / m + 1, y = (now - 1) % m + 1;
rep(i, 1, n*m) {
fa[now][i] = fa[now - 1][i];
ga[now][i] = ga[now - 1][i];
sa[now][i] = sa[now - 1][i];
ha[now][i] = ha[now - 1][i];
}
hole[now] = hole[now - 1] + 1;
if (con == 1 && cnt == t) {

}
else if (now > m) {
int sz = 0;
rep(i, 1, m) {
int x = (now - i - 1) / m + 1, y = (now - i - 1) % m + 1;
if (!a[x][y]) continue;
b[sz++] = get(fa[now], now - i);
}
sort(b, b + sz);
sz = unique(b, b + sz) - b;
if (sz < con) {
return;
}
}

if (y > 1 && !a[x][y - 1]) {
int fx = get(ha[now], now), fy = get(ha[now], now - 1);
if (fx != fy) {
if (!fx || !fy) ha[now][fx + fy] = 0;
else ha[now][fx] = fy;
hole[now]--;
}
}
if (x > 1 && !a[x - 1][y]) {
int fx = get(ha[now], now), fy = get(ha[now], now - m);
if (fx != fy) {
if (!fx || !fy) ha[now][fx + fy] = 0;
else ha[now][fx] = fy;
hole[now]--;
}
}
if (y==1 || y==m || x == 1 || x == n) {
int fx = get(ha[now], now);
if (fx) {
ha[now][fx] = 0; hole[now]--;
}
}

int flag = 1;
if (y > 1 && !a[x][y - 1]) {
int fx = get(ga[now], now), fy = get(ga[now], now - 1);
if (fx != fy) {
ga[now][fx] = fy;
if ((sa[now][fy] += sa[now][fx]) > 1) flag = 0;
}
}
if (x > 1 && !a[x - 1][y]) {
int fx = get(ga[now], now), fy = get(ga[now], now - m);
if (fx != fy) {
ga[now][fx] = fy;
if ((sa[now][fy] += sa[now][fx]) > 1) flag = 0;
}
}
if (flag) dfs(now + 1, cnt, con);

if (s[x][y] == 'O') return;
rep(i, 1, n*m) {
fa[now][i] = fa[now - 1][i];
ga[now][i] = ga[now - 1][i];
sa[now][i] = sa[now - 1][i];
ha[now][i] = ha[now - 1][i];
}
hole[now] = hole[now - 1];
a[x][y] = 1;
con++;
if (y > 1 && a[x][y-1]) {
int fx = get(fa[now], now), fy = get(fa[now], now - 1);
if (fx != fy) { fa[now][fx] = fy; con--; }
}
if (x > 1 && a[x-1][y]) {
int fx = get(fa[now], now), fy = get(fa[now], now - m);
if (fx != fy) { fa[now][fx] = fy; con--; }
}
dfs(now + 1, cnt + 1, con);
a[x][y] = 0;
}

int main() {
scanf("%d%d%d%d", &n, &m, &t, &h);
rep(i, 1, n) scanf("%s", s[i] + 1);
rep(i, 1, n) rep(j, 1, m) {
fa[0][i*m - m + j] = i*m - m + j;
ga[0][i*m - m + j] = i*m - m + j;
ha[0][i*m - m + j] = i*m - m + j;
sa[0][i*m - m + j] = s[i][j] == 'O';
hole[0] = 0;
}
ans = 0;
dfs(1, 0, 0);
printf("%d\n", ans);
return 0;
}