首页 > 代码库 > hdu4185 Oil Skimming

hdu4185 Oil Skimming

要用1×2的板子尽量多的覆盖##区域,且不能交叉,求至多可以覆盖多少板子。


每一个#向向下或向右相邻的#建边。求最大匹配就可以了。

其实这题数据是比较弱的把,应该是#的个数在600以内把。。


#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#pragma comment(linker, "/STACK:16777216")
#define eps 1e-6
#define ll long long
using namespace std;

int n,cnt,mx[605],my[605],vis[605],e[605][605],mp[605][605];
char s[605][605];

int path(int i)
{
    int j;
    for(j=1;j<cnt;j++)
    {
        if(e[i][j]&&!vis[j])
        {
            vis[j]=1;
            if(my[j]==-1||path(my[j]))
            {
                my[j]=i;
                mx[i]=j;
                return 1;
            }
        }
    }
    return 0;
}

int hungary()
{
    int res=0;
    memset(mx,-1,sizeof mx);
    memset(my,-1,sizeof my);
    for(int i=1;i<cnt;i++)
    {
        if(mx[i]==-1)
        {
            memset(vis,0,sizeof vis);
            res+=path(i);
        }
    }
    return res;
}

int main()
{
    int icy,cas=1,i,j;
    scanf("%d",&icy);
    while(icy--)
    {
        scanf("%d",&n);
        memset(e,0,sizeof e);
        memset(mp,0,sizeof mp);
        for(i=0;i<n;i++)
            scanf("%s",s[i]);
        cnt=1;
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
                if(s[i][j]=='#')
                     mp[i][j]=cnt++;
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
            {
                if(mp[i][j])
                {
                    if(i<n-1&&mp[i+1][j])
                        e[mp[i][j]][mp[i+1][j]]=e[mp[i+1][j]][mp[i][j]]=1;
                    if(j<n-1&&mp[i][j+1])
                        e[mp[i][j+1]][mp[i][j]]=e[mp[i][j]][mp[i][j+1]]=1;
                }
            }
        memset(vis,0,sizeof vis);
        int ans=hungary();
        printf("Case %d: %d\n",cas++,ans/2);
    }
    return 0;
}