我是靠谱客的博主 粗犷电脑,最近开发中收集的这篇文章主要介绍【TJOI2016&&HEOI2016】游戏,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Description

这里写图片描述

Solution

每个炸弹对整行整列都有约束,那么很显然的是二分图最大匹配,行向列连边,说明去了其中的一个就不能再取。
但是这题有软石头和硬石头的限制,怎么办?
我们可以发现有一些区间内是只能放一个炸弹的,那么我们横着把这种块统计出来,竖着再把这种块找出来(为了打着方便,两个#之间可以当做一个块),如果横着的块i和竖着的块j之间的交点是一个空格,那么就连边,说明如果在这两个块的交点放炸弹,只能放一个。
最后匈牙利就可以过了,但是我还是习惯用网络流来求最大匹配23333
秒切!

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=107,mxx=30007;
int i,j,k,l,t,n,m,ans;
char s[maxn][maxn];
int hk[mxx][3],sk[mxx][3],tot1,tot2;
int first[mxx*2],next[mxx*2],last[mxx*2],chang[mxx*2],num,T;
int d[mxx*2],fan[mxx*2];
bool bz[mxx*2],az;
void add(int x,int y,int z){
    last[++num]=y;next[num]=first[x];first[x]=num;chang[num]=z;fan[num]=num+1;
    last[++num]=x;next[num]=first[y];first[y]=num;chang[num]=0;fan[num]=num-1;
}
bool bfs(){
    int data[mxx*2],head=0,tail=1,i,j,now;
    memset(data,0,sizeof(data));
    memset(d,0,sizeof(d));d[0]=1;
    while(head<tail){
        now=data[++head];
        rep(i,now){
            if(chang[i]&&!d[last[i]]){
                d[last[i]]=d[now]+1;
                data[++tail]=last[i];
            }
        }
    }
    return d[T]!=0;
}
int dinic(int x,int y){
    if(x==T){
        return y;
    }
    int i,j,k=y,p=0;
    rep(i,x){
        if(chang[i]&&d[last[i]]==d[x]+1){
            j=dinic(last[i],min(y,chang[i]));
            if(j>0){
               chang[i]-=j;chang[fan[i]]+=j;
               p+=j;k-=j;
               if(k<=0)break;    
            }
        }
    }
    if(p==0)d[x]=-1;
    return p;
}
int main(){
    //freopen("fan.in","r",stdin);
    scanf("%d%d",&n,&m);
    fo(i,1,n){
        scanf("%s",s[i]+1);
    }
    fo(i,1,n){
        t=l=0;az=0;
        fo(j,1,n){
            if(s[i][j]=='*')az=1;
            if(t&&(s[i][j]=='*'||(s[i][j]=='x'))){
                l=j;continue;
            }
            if(!t&&s[i][j]=='*'||(s[i][j]=='x')){
                t=l=j;continue;
            }
            if(l&&s[i][j]=='#'&&az){
                hk[++tot1][0]=t,hk[tot1][1]=l;hk[tot1][2]=i;
                t=l=0;az=0;    
            }
            else if(s[i][j]=='#'){t=l=0;}
        }
        if(l&&az){hk[++tot1][0]=t,hk[tot1][1]=l;hk[tot1][2]=i;}
    }
    fo(j,1,n){
        t=l=0;az=0;
        fo(i,1,n){
            if(s[i][j]=='*')az=1;
            if(t&&(s[i][j]=='*'||(s[i][j]=='x'))){
                l=i;continue;
            }
            if(!t&&s[i][j]=='*'||(s[i][j]=='x')){
                t=l=i;continue;
            }
            if(l&&s[i][j]=='#'&&az){
                sk[++tot2][0]=t,sk[tot2][1]=l;sk[tot2][2]=j;
                t=l=0;az=0;    
            }
            else if(s[i][j]=='#'){t=l=0;}
        }
        if(l&&az){sk[++tot2][0]=t,sk[tot2][1]=l;sk[tot2][2]=j;}
    }
    fo(i,1,tot1){
        fo(j,1,tot2){
            if(s[hk[i][2]][sk[j][2]]=='*'&&sk[j][2]<=hk[i][1]&&sk[j][2]>=hk[i][0]&&hk[i][2]<=sk[j][1]&&hk[i][2]>=sk[j][0]){
                add(i,tot1+j,1);
            }
        }
    }
    T=tot1+tot2+1;
    fo(i,1,tot1)add(0,i,1);fo(i,1,tot2)add(i+tot1,T,1);
    while(bfs()){
        ans+=dinic(0,0x7fffffff);
    }
    printf("%dn",ans);
}

最后

以上就是粗犷电脑为你收集整理的【TJOI2016&&HEOI2016】游戏的全部内容,希望文章能够帮你解决【TJOI2016&&HEOI2016】游戏所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部