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#

Sample Output

5
 
每一行和每一列的每一个联通块建成一个点,如果有#就把当前行拆点
然后每一个空地建成一条连接两个点的边,然后答案就是二分图的最大匹配。
 1 #include<bits/stdc++.h>
 2 #define rep(i,l,r) for(int i=l;i<=r;++i)
 3 using namespace std;
 4 const int inf=2147483647,N=102333;
 5 int head[N],tot=1,cnt1,cnt2,T,id[100][100],sum,dis[N],n,m;
 6 char mp[100][100];
 7 struct zs{
 8     int to,next,w;
 9 }e[N];
10 inline void ins(int u,int v,int w){
11     e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w;
12 }
13 inline void insert(int u,int v,int w){
14     ins(u,v,w); ins(v,u,0);
15 }
16 inline bool bfs(){
17      for(int i=0;i<=T;i++) dis[i]=-1; queue<int>q; q.push(0); dis[0]=0;
18      while(!q.empty()) {
19           int x=q.front(); q.pop();
20           for(int k=head[x];k;k=e[k].next) 
21              if(dis[e[k].to]<0 && e[k].w>0) {
22                    dis[e[k].to]=dis[x]+1; q.push(e[k].to);
23              }
24      }
25      if(dis[T]>0) return 1;else return 0;
26 }
27 int find(int x,int low){
28      if(x==T) return low;
29      int delta=low,now;
30      for(int k=head[x];k;k=e[k].next) 
31        if(e[k].w>0 && dis[e[k].to]==dis[x]+1){ 
32            now=find(e[k].to,min(e[k].w,delta));
33            e[k].w-=now; e[k^1].w+=now;   delta-=now;
34            if(!delta) return low;
35         } 
36      dis[x]=-1;
37      return low-delta;
38 }
39 int main(){
40     scanf("%d%d",&n,&m);
41     rep(i,1,n) scanf("%s",mp[i]+1);
42     T=4000; cnt1=1;
43     rep(i,1,n) {
44         rep(j,1,m) cnt1+=(mp[i][j]=='#'),id[i][j]=cnt1;
45         ++cnt1;
46     }
47     cnt2=cnt1+1;
48     rep(j,1,m){
49         rep(i,1,n) if(mp[i][j]=='#') ++cnt2;else if(mp[i][j]=='*') insert(id[i][j],cnt2,1);
50         ++cnt2;
51     }
52     rep(i,1,cnt1) insert(0,i,1);
53     rep(i,cnt1+1,cnt2) insert(i,T,1);
54     while(bfs()) sum+=find(0,inf);
55     printf("%d\n",sum);
56 }
View Code

 

posted @ 2016-10-17 20:18  Bloodline  阅读(218)  评论(0编辑  收藏  举报