bzoj4554 [Tjoi2016&Heoi2016]游戏
Description
在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂。简单的说,这个游戏就是在一张地图上放上若干个炸弹,看是否能炸到对手,或者躲开对手的炸弹。在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。给定一张n*m的网格地图:其中*代表空地,炸弹的威力可以穿透,可以在空地上放置一枚炸弹。x代表软石头,炸弹的威力可以穿透,不能在此放置炸弹。#代表硬石头,炸弹的威力是不能穿透的,不能在此放置炸弹。例如:给出1*4的网格地图*xx*,这个地图上最多只能放置一个炸弹。给出另一个1*4的网格地图*x#*,这个地图最多能放置两个炸弹。现在小H任意给出一张n*m的网格地图,问你最多能放置多少炸弹
Input
第一行输入两个正整数n,m,n表示地图的行数,m表示地图的列数。1≤n,m≤50。接下来输入n行m列个字符,代表网格地图。*的个数不超过n*m个
Output
输出一个整数a,表示最多能放置炸弹的个数
Sample Input
```
4 4
#***
*#**
**#*
xxx#
```
4 4
#***
*#**
**#*
xxx#
```
Sample Output
5
正解:二分图最大匹配。
我真是个智障,一开始把这题做成了二分图最大独立集。。
如果一个点有炸弹,那么这个点的行向列连一条边,跑一遍最大匹配就行了,但是有石头,所以不能这么做。
解决石头的问题很简单,我们把每一行按照石头分开标号,每一列按照石头分开标号就行了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (100010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 struct edge{ int nt,to; }g[10*N]; 23 24 int h[60][60],l[60][60],head[N],vis[N],lk[N],n,m,sz1,sz2,num,cnt,ans; 25 char c[60][60]; 26 27 il int gi(){ 28 RG int x=0,q=1; RG char ch=getchar(); 29 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 30 if (ch=='-') q=-1,ch=getchar(); 31 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 32 return q*x; 33 } 34 35 il char gc(){ 36 RG char ch=getchar(); 37 while (ch!='*' && ch!='x' && ch!='#') ch=getchar(); 38 return ch; 39 } 40 41 il void insert(RG int from,RG int to){ 42 g[++num]=(edge){head[from],to},head[from]=num; return; 43 } 44 45 il int dfs(RG int x){ 46 for (RG int i=head[x],v;i;i=g[i].nt){ 47 v=g[i].to; if (vis[v]==cnt) continue; vis[v]=cnt; 48 if (!lk[v] || dfs(lk[v])){ lk[v]=x; return 1; } 49 } 50 return 0; 51 } 52 53 il void work(){ 54 n=gi(),m=gi(); 55 for (RG int i=1;i<=n;++i) 56 for (RG int j=1;j<=m;++j) c[i][j]=gc(); 57 for (RG int i=1;i<=n;++i) 58 for (RG int j=1;j<=m;++j){ 59 if (j==1 || c[i][j-1]=='#') ++sz1; h[i][j]=sz1; 60 } 61 for (RG int j=1;j<=m;++j) 62 for (RG int i=1;i<=n;++i){ 63 if (i==1 || c[i-1][j]=='#') ++sz2; l[i][j]=sz2; 64 } 65 for (RG int i=1;i<=n;++i) 66 for (RG int j=1;j<=m;++j) 67 if (c[i][j]=='*') insert(h[i][j],l[i][j]); 68 for (RG int i=1;i<=sz1;++i){ ++cnt; if (dfs(i)) ++ans; } 69 printf("%d\n",ans); return; 70 } 71 72 int main(){ 73 File("game"); 74 work(); 75 return 0; 76 }