【Tjoi2016&Heoi2016】游戏

来源:互联网 发布:js原生排序 编辑:程序博客网 时间:2024/04/29 22:58

Description

这里写图片描述

Solution

naive的我这题只能打暴力了......

这题我们考虑炸弹炸的区域,它只和它所在的行和列有关,于是这个位置能放炸弹,那么就是该炸弹所在行和列的匹配。

但是,这题有许多石头,有些硬石头炸弹还炸不穿。那么,这个炸弹在这个硬石头的一个方向爆炸,这个石头的相反方向的位置不会受到任何影响。

所以我们独立每个被硬石头隔开的横向联通块和竖向连通块,对于一个空地,如果它被横向连通块和竖向连通块所包含,那么这两个连通块连一条边。

然后,做一次最大匹配即可。

Code

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 60using namespace std;int map[N][N];int ans=0;int n,m;struct node{    int x,y;}b[N][N];bool bz[N*N];bool f[N*N][N*N];int g[N*N];int p,cnt=0;bool find(int x){    fo(i,p,cnt)    if(f[x][i] && !bz[i])    {        bz[i]=true;        if(!g[i] || find(g[i]))        {            g[i]=x;            return true;        }    }    return false;}int main(){    cin>>n>>m;    fo(i,1,n)    {        char s[N];        scanf("%s",s+1);        fo(j,1,m)        if(s[j]=='x') map[i][j]=1;        else if(s[j]=='#') map[i][j]=2;    }    fo(i,1,n)    {        map[i][0]=2;        cnt++;        fo(j,1,m+1)        {            if(map[i][j]==2 && map[i][j-1]!=2) cnt++;            b[i][j].x=cnt;        }    }    p=cnt+1;    fo(i,1,m)    {        map[0][i]=2;        cnt++;        fo(j,1,n)        {            if(map[j][i]==2 && map[j-1][i]!=2) cnt++;            b[j][i].y=cnt;        }    }    fo(i,1,n)    fo(j,1,m)    if(!map[i][j]) f[b[i][j].x][b[i][j].y]=true;    int ans=0;    fo(i,1,p-1)    {        memset(bz,0,sizeof(bz));        if(find(i)) ans++;    }    cout<<ans;}
2 0