1. 程式人生 > >[HEOI2016/TJOI2016]遊戲

[HEOI2016/TJOI2016]遊戲

Description
在2016年,佳緣姐姐喜歡上了一款遊戲,叫做泡泡堂。簡單的說,這個遊戲就是在一張地圖上放上若干個炸彈,看是否能炸到對手,或者躲開對手的炸彈。在玩遊戲的過程中,小H想到了這樣一個問題:當給定一張地圖,在這張地圖上最多能放上多少個炸彈能使得任意兩個炸彈之間不會互相炸到。炸彈能炸到的範圍是該炸彈所在的一行和一列,炸彈的威力可以穿透軟石頭,但是不能穿透硬石頭。給定一張nm的網格地圖:其中代表空地,炸彈的威力可以穿透,可以在空地上放置一枚炸彈。x代表軟石頭,炸彈的威力可以穿透,不能在此放置炸彈。#代表硬石頭,炸彈的威力是不能穿透的,不能在此放置炸彈。例如:給出14的網格地圖xx,這個地圖上最多隻能放置一個炸彈。給出另一個1

4的網格地圖x#,這個地圖最多能放置兩個炸彈。現在小H任意給出一張n*m的網格地圖,問你最多能放置多少炸彈

Input
第一行輸入兩個正整數n,m,n表示地圖的行數,m表示地圖的列數。1≤n,m≤50。接下來輸入n行m列個字元,代表網格地圖。的個數不超過nm個

Output
輸出一個整數a,表示最多能放置炸彈的個數

Sample Input

4 4
#***
*#**
**#*
xxx#

Sample Output
5

考慮如果沒有硬石頭,那麼對於每個能放置炸彈的點,將其所在行向所在列連邊即可。如果存在硬石頭,則將改行列分成了兩個區域,於是我們對這這些區域重新編號,然後連邊求最大匹配即可

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
#define lowbit(x) ((x)&-(x))
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
    int x=0,f=1; char ch=gc();
    for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline int read(){
    int x=0,f=1; char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x<0)    putchar('-'),x=-x;
    if (x>9)    print(x/10);
    putchar(x%10+'0');
}
const int N=2e3,M=4e3;
int pre[M+10],now[N+10],child[M+10];
int path[N+10],vis[N+10];
int tot,Time;
int row[55][55],col[55][55];//column
char map[55][55];
void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
bool Extra(int x){
    for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
        if (vis[son]==Time) continue;
        vis[son]=Time;
        if (!~path[son]||Extra(path[son])){
            path[son]=x;
            return 1;
        }
    }
    return 0;
}
int main(){
    memset(path,255,sizeof(path));
    int n=read(),m=read(),Row=0,Col=0,Ans=0;
    for (int i=1;i<=n;i++)  scanf("%s",map[i]+1);
    for (int i=1;i<=n;i++){
        for (int j=1;j<=m;j++){
            if (map[i][j]=='#') continue;
            if (j==1||map[i][j-1]=='#') Row++;
            row[i][j]=Row;
        }
    }
    for (int j=1;j<=m;j++){
        for (int i=1;i<=n;i++){
            if (map[i][j]=='#') continue;
            if (i==1||map[i-1][j]=='#') Col++;
            col[i][j]=Col;
        }
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (map[i][j]=='*')
                join(row[i][j],col[i][j]);
    for (int i=1;i<=Row;i++){
        ++Time;
        if (Extra(i))   ++Ans;
    }
    printf("%d\n",Ans);
    return 0;
}