zoj 1654 Place the Robots

/*
zoj_1654    最大流(最大二分匹配)
这题大家可以看黄源河大牛的论文,很牛B的建图思路。
匈牙利算法易解之。
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <string.h>
#define N 2550
using namespace std;
char map[55][55];
bool gra[N][N],state[N];
int result[N];
int n,m;
struct block
{
    int id,stax,stay,endx,endy;
    block( int a,int b,int c,int d,int e ):
    id(a),stax(b),stay(c),endx(d),endy(e)   {}
};
vector <block>ver,hor;

void build()
{
    int i,j,k,id;
    id=1;
    for( i=0;i<m;i++ )
    {
        for( j=0;j<n; )
            if( map[i][j]=='o' )
            {
                for( k=j+1;k<n;k++ )
                {
                    if( map[i][k]=='#' )
                        break;
                }
                hor.push_back( block( id++,i,j,i,k-1 ) );
                j=k+1;
            }
            else j++;
    }
    id=1;
    for( i=0;i<n;i++ )
    {
        for( j=0;j<m; )
            if( map[j][i]=='o' )
            {
                for( k=j+1;k<m;k++ )
                {
                    if( map[k][i]=='#' )
                        break;
                }
                ver.push_back( block( id++,j,i,k-1,i ) );
                j=k+1;
            }
            else j++;
    }
}

void graph()
{
    int i,j;
    memset( result,0,sizeof(result) );
    memset( gra,0,sizeof(gra) );
    for( i=0;i<hor.size();i++ )
    {
        for( j=0;j<ver.size();j++ )
            if( ver[j].stay>=hor[i].stay && ver[j].stay<=hor[i].endy
               && hor[i].stax>=ver[j].stax && hor[i].stax<=ver[j].endx
               && map[ hor[i].stax ][ ver[j].stay ]=='o' )
            gra[ hor[i].id ][ ver[j].id ]=true;
    }
}

bool find( int a )
{
    int i;
    for( i=1;i<=ver.size();i++ )
    {
        if( gra[a][i] && !state[i] )
        {
            state[i]=1;
            if( !result[i] || find( result[i] ) )
            {
                result[i]=a;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    int T,i,j,ans,co;
    scanf( "%d",&T );
    co=1;
    while( T-- )
    {
        scanf( "%d%d",&m,&n );
        getchar();
        for( i=0;i<m;i++ )
        {
            for( j=0;j<n;j++ )
                scanf( "%c",&map[i][j] );
            getchar();
        }
        build();
        graph();
        ans=0;
        for( i=1;i<=hor.size();i++ )
        {
            memset( state,0,sizeof(state) );
            if( find(i) ) ans++;
        }
        printf( "Case :%d\n%d\n",co,ans );
        co++;
        hor.clear();
        ver.clear();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值