POJ-2446-Chessboard(二分图匹配)

链接:https://vjudge.net/problem/POJ-2446#author=0

题意:

有一天,罗老板画了一块尺寸为M * N的棋盘。他希望许老师能够使用1 * 2的牌来覆盖棋盘。然而,他认为这很容易,所以他增大了难度,他在棋盘上打了一些洞

许老师必须遵守以下规则: 
1.任何不是洞网格都应该只被一张卡覆盖。 
2. 一张卡应该正好覆盖2个相邻非洞网格。 
3. 洞不可以被卡片覆盖

你的任务是帮助许老师确定 根据上述规则 是否存在一种方案可以覆盖棋盘

思路:

二分图匹配.因为一个1*2的方块,所放的两个格子,一个格子的x+y是偶数,一个是奇数,所以可以以x+y根据奇偶建图,再去求二分图。

代码:

#include <iostream>
#include <memory.h>
#include <string>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <algorithm>
#include <map>
#include <queue>
#include <math.h>
#include <cstdio>
#include <set>
#include <iterator>
#include <cstring>
using namespace std;

typedef long long LL;
const int MAXN = 2000;
int Next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};

int Dis[40][40];
int G[MAXN][MAXN];
int Link[MAXN];
bool Used[MAXN];
int n, m, k;
int cnt1, cnt2;

bool Dfs(int x)
{
    for (int node = 1;node <= cnt2;node++)
    {
        if (G[x][node] == 1 && Used[node] == false)
        {
            Used[node] = true;
            if (Link[node] == -1 || Dfs(Link[node]))
            {
                Link[node] = x;
                return true;
            }
        }
    }
    return false;
}

int Solve()
{
    int res = 0;
    memset(Link, -1, sizeof(Link));
    for (int i = 1;i <= cnt1;i++)
    {
        memset(Used, 0, sizeof(Used));
        if (Dfs(i))
            res++;
    }
    return res;
}

int main()
{
    while (cin >> n >> m >> k)
    {
        memset(Dis, 0, sizeof(Dis));
        int y, x;
        for (int i = 1;i <= k;i++)
        {
            cin >> y >> x;
            Dis[x][y] = -1;
        }
        cnt1 = cnt2 = 0;
        for (int i = 1;i <= n;i++)
        {
            for (int j = 1;j <= m;j++)
            {
                if (Dis[i][j] != -1)
                {
                    if ((i+j)%2 == 0)
                        Dis[i][j] = ++cnt1;
                    else
                        Dis[i][j] = ++cnt2;
                }
            }
        }
        for (int i = 1;i <= n;i++)
        {
            for (int j = 1;j <= m;j++)
            {
                if (Dis[i][j] != -1 && (i+j)%2 == 0)
                {
                    for (int k = 0;k < 4;k++)
                    {
                        int tx = i+Next[k][0];
                        int ty = j+Next[k][1];
                        if (tx < 1 || tx > n || ty < 1 || ty > m)
                            continue;
                        G[Dis[i][j]][Dis[tx][ty]] = 1;
                    }
                }
            }
        }
        if ((n*m-k)%2 == 1 || cnt1 != cnt2)
        {
            cout << "NO" << endl;
            continue;
        }
        int res = Solve();
        if (res == (n*m-k)/2)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }

    return 0;
}

  

原文地址:https://www.cnblogs.com/YDDDD/p/10859069.html

时间: 2024-10-10 10:02:11

POJ-2446-Chessboard(二分图匹配)的相关文章

poj 2446 Chessboard (二分图利用奇偶性匹配)

Chessboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13176   Accepted: 4118 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of cards with size 1 * 2

POJ 2446 Chessboard (二分图最大匹配)

题目链接:http://poj.org/problem?id=2446 给你一个n*m的棋盘,其中有k个洞,现在有1*2大小的纸片,纸片不能覆盖洞,并且每个格子最多只能被覆盖一次.问你除了洞口之外这个棋盘是否能被纸片填满. 这个题目一眼很难看出是二分图匹配... 可以根据i和j性质可以看出,i+j为奇数的上下相邻的i'和j'一定是偶数,那么一个1*2的纸片的i+j一定是一个奇数一个偶数.所以我是建立一个二分图两个集合,将i+j为奇数的点与上下左右相邻的点连在一起,当然点不是洞.最后就用匈牙利算法

poj 2446 Chessboard (二分匹配)

Chessboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12800   Accepted: 4000 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of cards with size 1 * 2

POJ - 2446 Chessboard 二分图 最大匹配(输入坑)

题目大意:有一个n*m的棋盘,棋盘上面有k个洞. 现在要求你在这棋盘上面放1*2的矩形,使得棋盘上除k个洞之外的所有点都被1 * 2的矩形覆盖,且只覆盖一次 解题思路:思路不难想到,将每一点作为两个点集(除洞之外),点集之间的联系表示该点能联通的点,这样二分图就构造完成了 只需要求出最大匹配数,再和n * m -k比较即可 输入是个坑啊,输入的坐标是(x,y),但是表示的缺失y行,x列 #include<cstdio> #include<cstring> #include<v

POJ 3057 Evacuation 二分图匹配

每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间. 不断增加时间,然后增广,直到最大匹配. //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<

POJ 2446 Chessboard

要求用占两格的长方形铺满平面上除去指定点 二分图匹配 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int dx[]={1,-1,0,0}; 6 int dy[]={0,0,1,-1}; 7 int map[40][40]; 8 int vis[40][40]; 9 int link[40*40]; 10 int m,n,k; 11 bool

poj 3692 Kindergarten(二分图匹配)

题意:n个男孩相互认识,m个女孩相互认识,k对男孩和女孩相互认识,求最大的任意两人相互认识的集合: 思路:二分图匹配: 独立集=总数-最大匹配数: 最大团=原图补图的最大独立集=总数-补图的最大匹配数: 本题就是求最大团,先求补图的最大匹配数,匈牙利算法: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,n,m; int mm[505][505]; int

POJ 2446 Chessboard(二分图最大匹配)

题意: M*N的棋盘,规定其中有K个格子不能放任何东西.(即不能被覆盖) 每一张牌的形状都是1*2,问这个棋盘能否被牌完全覆盖(K个格子除外) 思路: M.N很小,把每一个可以覆盖的格子都离散成一个个点,然后二分图最大匹配. 一个重要的问题**:可不可能存在建完的图是这样的情况:1-2,2-3,3-4,4-5,5-1?这种情况二分图最大匹配是5,但实际上答案是不对的. 证明:不可能存在这样的由奇个点构成的环图.我们按这种方法来看看能不能构造出这样一个棋盘. 假设有2k+1个个格(奇数),则第k+

POJ 3020-Antenna Placement(二分图匹配_最小路径覆盖+前向星构图)

Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6930   Accepted: 3439 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most st

Poj(1274),二分图匹配

题目链接:http://poj.org/problem?id=1274 The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 23088   Accepted: 10285 Description Farmer John completed his new barn just last week, complete with all the latest milking technology.