HDU 4619 Warm up 2 解题报告

来源:互联网 发布:数据交叉分析 编辑:程序博客网 时间:2024/05/17 21:41

比赛

题目

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

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

//time 31MS//memory 1332K#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#define MAXN 1015using 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;}


原创粉丝点击