PAT (Top Level) Practise 1019 Separate the Animals (35)

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值