首先因为草坪并不影响互相攻击,所以应该把整个图每一行按照墙分成不同的连通块并且编号,同理编号竖向的连通块,但是因为机器人不能放在草坪上所以只有当两个连通块的交点的地方为空地的时候机器人才能够站立,那么按照http://blog.csdn.net/jeremygjy/article/details/47087593改一下数据范围改一下建边的时候检查一下是否为空地就好了。
#include <cstdio>
#include <cstring>
#include <algorithm>
//#include <conio.h>
using namespace std;
const int MAXN = 50;
bool vis[MAXN*MAXN];
int Map[MAXN+2][MAXN+2];
int id_v[MAXN+2][MAXN+2];
int id_h[MAXN+2][MAXN+2];
int con[MAXN*MAXN];
int idcnt, endcnt;
int n, m;
const int MAXM = MAXN * MAXN;
struct node{
int v;
node *next;
}Edges[MAXM*2+10], *adj[MAXM+10], *ecnt=Edges;
void addedge(int u, int v){
++ecnt;
ecnt->v = v;
ecnt->next = adj[u];
adj[u] = ecnt;
}
bool dfs(int u){
for(node *p=adj[u];p;p=p->next){
if(!vis[p->v]){
vis[p->v] = true;
if(!con[p->v] || dfs(con[p->v])){
con[u] = p->v;
con[p->v] = u;
return true;
}
}
}
return false;
}
int work(){
int ret = 0;
for(int i=1;i<=endcnt;i++) if(!con[i]) {
memset(vis, 0, sizeof vis);
ret += dfs(i);
}
return ret;
}
void read(){
char t[60];
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++){
scanf("%s", t);
for(int j=0;j<m;j++){
if(t[j] == '#')
Map[i][j+1] = 0;
else if(t[j] == '*')
Map[i][j+1] = 1;
else
Map[i][j+1] = 2;
}
}
}
void prepare(){
idcnt=0;
memset(adj, 0, sizeof adj);
ecnt=Edges;
memset(con, 0, sizeof con);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) if(Map[i][j]){
if(!Map[i][j-1]) idcnt++;
id_h[i][j] = idcnt;
}
}
endcnt = idcnt;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++) if(Map[j][i]) {
if(!Map[j-1][i]) idcnt++;
id_v[j][i] = idcnt;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) if(Map[i][j] == 2){
addedge(id_h[i][j], id_v[i][j]);
addedge(id_v[i][j], id_h[i][j]);
}
}
}
int main(){
int T, Tcnt=0;
scanf("%d", &T);
while(Tcnt++ < T){
read();
prepare();
printf("Case :%d\n%d\n", Tcnt, work());
}
return 0;
}