和HDU 5093 是一样的
题意:
在一个Y行X列的网格里有空地(.),重要位置(*)和障碍物(#),用最少的机器人看守所有重要位置,每个机器人要放在一个格子里,面朝上下左右4个方向之一。机器人会发出激光,一直射到障碍物为止,沿途都是看守范围。
思路:给行块和列块标号,在重要位置处连边,然后匹配
#include <stdio.h>
#include <string.h>
int str[105][105];
int match[2550],x[105][105],y[105][105];
bool mp[2500][2500],used[2550];
int cntx,cnty;
bool dfs(int u)
{
for(int i = 0; i < cnty; i++) {
if(mp[u][i] && !used[i]) {
used[i] = 1;
if(match[i] == -1 || dfs(match[i])) {
match[i] = u;
return true;
}
}
}
return false;
}
int max_match()
{
int ans = 0;
memset(match,-1,sizeof(match));
for(int i = 0; i < cntx; i++) {
memset(used,0,sizeof(used));
if(dfs(i)){
ans++;
}
}
return ans;
}
int main(void)
{
int T;
scanf("%d",&T);
while(T--) {
int n,m;
scanf("%d%d",&n,&m);
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(mp,0,sizeof(mp));
memset(str,0,sizeof(str));
int p,xx,yy;
scanf("%d",&p);
while(p--) {
scanf("%d %d",&xx,&yy);
xx--;yy--;
str[xx][yy] = 1;
}
scanf("%d",&p);
while(p--) {
scanf("%d %d",&xx,&yy);
xx--;yy--;
str[xx][yy] = 2;
}
cntx = -1;
for(int i = 0; i < n; i++) {
bool flag = true;
for(int j = 0; j < m; j++) {
if(str[i][j] == 1) {
if(flag) ++cntx;
x[i][j] = cntx;
flag = false;
}
if(str[i][j] == 2) {
flag = true;
}
}
}
//给列块标号
cnty = -1;
for(int i = 0; i < m; i++) {
bool flag = true;
for(int j = 0; j < n; j++) {
if(str[j][i] == 1) {
if(flag) ++cnty;
y[j][i] = cnty;
flag = false;
}
if(str[j][i] == 2) {
flag = true;
}
}
}
cntx++;
cnty++;
//建图
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(str[i][j] == 1) {
mp[x[i][j]][y[i][j]] = 1;
}
}
}
printf("%d\n",max_match());
}
return 0;
}