链接: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;
}