POJ 2226 Muddy Fields(二分匹配)

题目大意:给一个n*m的方格地图,每个方格中有一个字符,'.'草地,'*'泥巴地,给你一些宽为1方格大小的板子,长度不限,问最少需要多少板子才能盖住所有的泥巴地,但是不能盖住草地,板子允许相互覆盖。

分析:扫描行,将连通的泥巴地看成一个结点,这样得到二分图的X部,按同样的方法扫描列得到二分图的Y部,有公共方格的结点之间连边。

View Code
#include <stdio.h>
#include <string.h>
#define N 51
#define M 51
char map[N][M];
bool g[N*M][N*M];
int n,m;
int x[N*M],y[N*M],vis[N*M];
int a[N][M],b[N][M],cnt1,cnt2;
void build()
{
    int i,j;
    cnt1=0;
    for(i=0;i<n;i++)
    {
        for(j=0;j<m;j++)    if(map[i][j]=='*')
        {
            if(j==0 || map[i][j-1]!='*')    cnt1++;
            a[i][j]=cnt1;
        }
    }
    cnt2=0;
    for(j=0;j<m;j++)
    {
        for(i=0;i<n;i++)    if(map[i][j]=='*')
        {
            if(i==0 || map[i-1][j]!='*')    cnt2++;
            b[i][j]=cnt2;
        }
    }
    memset(g,0,sizeof(g));
    for(i=0;i<n;i++)
    {
        for(j=0;j<m;j++)    if(map[i][j]=='*')
        {
            g[a[i][j]][b[i][j]]=1;
        }
    }
}
int path(int u)
{
    for(int v=1;v<=cnt2;v++)    if(g[u][v] && !vis[v])
    {
        vis[v]=1;
        if(y[v]==-1 || path(y[v]))
        {
            x[u]=v;
            y[v]=u;
            return 1;
        }
    }
    return 0;
}
int maxmatch()
{
    int ret=0;
    memset(x,-1,sizeof(x));
    memset(y,-1,sizeof(y));
    for(int u=1;u<=cnt1;u++)
    {
        memset(vis,0,sizeof(vis));
        if(x[u]==-1)    ret+=path(u);
    }
    return ret;
}
int main()
{
    int i;
    while(~scanf("%d%d",&n,&m))
    {
        for(i=0;i<n;i++)    scanf("%s",map[i]);
        build();
        printf("%d\n",maxmatch());
    }
    return 0;
}
posted @ 2012-08-01 17:19  BeatLJ  阅读(252)  评论(0编辑  收藏  举报