题目描述
在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂。简单的说,这个游戏就是在一张地图上放上若干个炸弹,看是否能炸到对手,或者躲开对手的炸弹。在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。给定一张n*m的网格地图:其中*代表空地,炸弹的威力可以穿透,可以在空地上放置一枚炸弹。x代表软石头,炸弹的威力可以穿透,不能在此放置炸弹。#代表硬石头,炸弹的威力是不能穿透的,不能在此放置炸弹。例如:给出1*4的网格地图*xx*,这个地图上最多只能放置一个炸弹。给出另一个1*4的网格地图*x#*,这个地图最多能放置两个炸弹。现在小H任意给出一张n*m的网格地图,问你最多能放置多少炸弹。
输入输出格式
输入格式:
第一行输入两个正整数n,m,n表示地图的行数,m表示地图的列数。1≤n,m≤50。接下来输入n行m列个字符,代表网格地图。*的个数不超过n*m个。
输出格式:
输出一个整数a,表示最多能放置炸弹的个数
输入输出样例
输入样例#1:
4 4 #∗∗∗ ∗#∗∗ ∗∗#∗ xxx#
输出样例#1:
5
套路题
行和列构成二分图,把所有的*作为边,跑匹配
问题在于这个构图比较麻烦,#会把一行/列分成两个
可以预先把每个格子所在的行和列的编号处理出来
注意最多会有1250*2+2个点
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 #include <string> 6 #include <cstring> 7 #include <cmath> 8 #include <map> 9 #include <stack> 10 #include <set> 11 #include <vector> 12 #include <queue> 13 #include <time.h> 14 #define eps 1e-7 15 #define INF 0x3f3f3f3f 16 #define MOD 1000000007 17 #define rep0(j,n) for(int j=0;j<n;++j) 18 #define rep1(j,n) for(int j=1;j<=n;++j) 19 #define pb push_back 20 #define set0(n) memset(n,0,sizeof(n)) 21 #define ll long long 22 #define ull unsigned long long 23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt) 24 #define max(a,b) (a>b?a:b) 25 #define min(a,b) (a<b?a:b) 26 #define print_runtime printf("Running time:%.3lfs ",double(clock())/1000.0) 27 #define TO(j) printf(#j": %d ",j); 28 //#define OJ 29 using namespace std; 30 const int MAXINT = 100010; 31 const int MAXNODE = 3000; 32 const int MAXEDGE = 10000; 33 char BUF,*buf; 34 int read(){ 35 char c=getchar();int f=1,x=0; 36 while(!isdigit(c)){if(c=='-') f=-1;c=getchar();} 37 while(isdigit(c)){x=x*10+c-'0';c=getchar();} 38 return f*x; 39 } 40 char get_ch(){ 41 char c=getchar(); 42 while(!isalpha(c)) c=getchar(); 43 return c; 44 } 45 //------------------- Head Files ----------------------// 46 47 int n,m,cnt,q[MAXNODE],dis[MAXNODE],SS=MAXNODE-2,TT=MAXNODE-1,id_h[51][51],id_v[51][51],cnt_h,cnt_v; 48 char mat[51][51]; 49 struct edge{ 50 int u,v,c; 51 edge *nxt; 52 edge(int _u,int _v,int _c,edge * _nxt):u(_u),v(_v),c(_c),nxt(_nxt){} 53 edge(){} 54 }mp[MAXEDGE],*head[MAXNODE]; 55 void addedge(int u,int v,int c){ 56 mp[cnt] = edge(u,v,c,head[u]); 57 head[u] = &mp[cnt++]; 58 mp[cnt] = edge(v,u,0,head[v]); 59 head[v] = &mp[cnt++]; 60 } 61 edge *rev(edge *e){ 62 return &mp[(e-mp)^1]; 63 } 64 int bfs(int ss,int tt){ 65 memset(dis,-1,sizeof(dis)); 66 int *h,*t,p; 67 h=t=q; 68 dis[ss]=0; 69 *t++=ss; 70 while(h!=t){ 71 p=*h++; 72 iter(i,p){ 73 if(i->c&&dis[i->v]==-1){ 74 dis[i->v]=dis[p]+1; 75 *t++=i->v; 76 } 77 } 78 } 79 return dis[tt]!=-1; 80 } 81 int dfs(int u,int v,int flow){ 82 int tmp,flow_t=0; 83 if(u==v) return flow; 84 iter(i,u){ 85 if(i->c&&dis[i->v]==dis[u]+1&&(tmp=dfs(i->v,v,min(i->c,flow-flow_t)))){ 86 flow_t+=tmp; 87 i->c-=tmp; 88 rev(i)->c+=tmp; 89 } 90 } 91 if(flow_t==0) dis[u]=-1; 92 return flow_t; 93 } 94 int dinic(int ss,int tt){ 95 int ans=0,tmp; 96 while(bfs(ss,tt)){ 97 while(tmp=dfs(ss,tt,INF)) ans+=tmp; 98 } 99 return ans; 100 } 101 void get_input(); 102 void work(); 103 int main() { 104 get_input(); 105 work(); 106 return 0; 107 } 108 void work(){ 109 rep0(i,n){ 110 rep0(j,m){ 111 if(mat[i][j]=='*') id_h[i][j]=cnt_h; 112 if(mat[i][j]=='#') cnt_h++; 113 } 114 cnt_h++; 115 } 116 rep0(i,m){ 117 rep0(j,n){ 118 if(mat[j][i]=='*') id_v[j][i]=cnt_v; 119 if(mat[j][i]=='#') cnt_v++; 120 } 121 cnt_v++; 122 } 123 rep0(i,cnt_h) addedge(SS,i,1); 124 rep0(i,cnt_v) addedge(i+cnt_h,TT,1); 125 rep0(i,n){ 126 rep0(j,m){ 127 if(mat[i][j]=='*') addedge(id_h[i][j],id_v[i][j]+cnt_h,1); 128 } 129 } 130 printf("%d ",dinic(SS,TT)); 131 } 132 void get_input(){ 133 n=read();m=read(); 134 rep0(i,n){ 135 scanf("%s",mat[i]); 136 } 137 } 138 /* 139 4 5 140 ***** 141 #*#*# 142 ***** 143 #*#*# 144 */