HDU 4619 Warm up 2 解题报告

比赛

题目

题意:给定1×2的多米诺骨牌,放在平面上,可以水平放也可以竖直放,保证水平和水平的之间不重叠,竖直和竖直的不重叠,但水平和竖直的可能重叠。拿走一些牌使它们,不重叠,求平面上最多可以剩张牌。

解法:在重叠的牌之间连边构成二分图,有边相连说明至多只有一张牌能留在平面上。YY出来的结论是,用总牌数减去最大匹配即为所求。

//time 31MS	
//memory 1332K
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAXN 1015
using namespace std;
struct Point{
    int x,y;
    Point(){}
    Point(int a,int b):x(a),y(b){}
    bool operator ==(const Point &a)const
    {
        return x==a.x&&y==a.y;
    }
    void input(){scanf("%d%d",&x,&y);}
};
int link[MAXN],n,m;
bool vis[MAXN],g[MAXN][MAXN];
bool judge(Point a, Point b)
{
    if(a==b||Point(a.x+1,a.y)==b||Point(a.x+1,a.y)==Point(b.x,b.y+1)||a==Point(b.x,b.y+1))
        return 1;
    return 0;
}
bool dfs(int u)
{
    for(int i = 0;i < m; i++)
    {
        if(!vis[i]&&g[u][i])
        {
            vis[i] = 1;
            if(link[i]==-1||dfs(link[i]))
            {
                link[i] = u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    //freopen("/home/moor/Code/input","r",stdin);
    Point pn[MAXN],pm[MAXN];
    while(scanf("%d%d",&n,&m)&&(m+n))
    {
        memset(g,0,sizeof(g));
        for(int i = 0; i < n; i++)
            pn[i].input();
        for(int i = 0; i < m; i++)
            pm[i].input();
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                if(judge(pn[i],pm[j]))
                    g[i][j] = 1;
        memset(link,-1,sizeof(link));
        int sum=0;
        for(int i = 0; i < n; i++)
        {
            memset(vis,0,sizeof(vis));
            sum+=dfs(i);
        }
        printf("%d\n",n+m-sum);
    }
    return 0;
}


你可能感兴趣的:(HDU 4619 Warm up 2 解题报告)