题意,在m*n的图中,把k个点除开后,看能否用1*2的木块把图完全覆盖,不能重叠,考虑到集合,把每对点当作匹配边,如果最大匹配是n*m-k,则YES
ChessboardTime Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu
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 to cover the board. However, she thinks it too easy to bob, so she makes some holes on the board (as shown in the figure below).
We call a grid, which doesn’t contain a hole, a normal grid. Bob has to follow the rules below:
1. Any normal grid should be covered with exactly one card.
2. One card should cover exactly 2 normal adjacent grids.
Some examples are given in the figures below:
A VALID solution.
An invalid solution, because the hole of red color is covered with a card.
An invalid solution, because there exists a grid, which is not covered.
Your task is to help Bob to decide whether or not the chessboard can be covered according to the rules above.
We call a grid, which doesn’t contain a hole, a normal grid. Bob has to follow the rules below:
1. Any normal grid should be covered with exactly one card.
2. One card should cover exactly 2 normal adjacent grids.
Some examples are given in the figures below:
A VALID solution.
An invalid solution, because the hole of red color is covered with a card.
An invalid solution, because there exists a grid, which is not covered.
Your task is to help Bob to decide whether or not the chessboard can be covered according to the rules above.
Input
There are 3 integers in the first line: m, n, k (0 < m, n <= 32, 0 <= K < m * n), the number of rows, column and holes. In the next k lines, there is a pair of integers (x, y) in each line, which represents a hole in the y-th row, the x-th column.
Output
If the board can be covered, output "YES". Otherwise, output "NO".
Sample Input
4 3 2 2 1 3 3
Sample Output
YES
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define maxn 35
#define maxn1 33*33
using namespace std;
int n, m, k;
int cnt;
int W[maxn1][maxn1];
int map[maxn][maxn];
int lef[maxn1];
bool T[maxn1];
bool vis[maxn][maxn];
bool match(int i)
{
for (int j = 1; j <= cnt; j++)
{
if (W[i][j] && !T[j])
{
T[j] = true;
if (lef[j] == 0 || match(lef[j]))
{
lef[j] = i;
return true;
}
}
}
return false;
}
void KM()
{
int sum = 0;
for (int i = 1; i <= cnt; i++)
{
memset(T, 0, sizeof(T));
if (match(i))
{
sum++;
}
}
if (sum == m*n-k)
printf("YES\n");
else
printf("NO\n");
}
int main()
{
while (scanf("%d%d%d", &m, &n, &k) != EOF)
{
memset(W, 0, sizeof(W));
memset(lef, 0, sizeof(lef));
memset(vis, 0, sizeof(vis));
int a, b;
for (int j = 1; j <= k; j++)
{
scanf("%d%d", &a, &b);
vis[b][a] = 1;
}
cnt = 1;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
{
if (!vis[i][j])//把每个点标记,就能存进M[][]
map[i][j] = cnt++;
}
cnt--;
if ((cnt - k) & 1)
printf("NO\n");
else
{
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
{
if (!vis[i][j])
{
//四个方向
if (i > 1 && !vis[i - 1][j])
W[map[i][j]][map[i - 1][j]] = 1;
if (i < m&&!vis[i + 1][j])
W[map[i][j]][map[i + 1][j]] = 1;
if (j > 1 && !vis[i][j - 1])
W[map[i][j]][map[i][j - 1]] = 1;
if (j < n&&!vis[i][j + 1])
W[map[i][j]][map[i][j + 1]] = 1;
}
}
KM();
}
}
return 0;
}