题目描述
给定一个N行N列的棋盘,已知某些格子禁止放置。
求最多能往棋盘上放多少块的长度为2、宽度为1的骨牌,骨牌的边界与格线重合(骨牌占用两个格子),
并且任意两张骨牌都不重叠。
输入格式
第一行包含两个整数N和t,其中t为禁止放置的格子的数量。
接下来t行每行包含两个整数x和y,表示位于第x行第y列的格子禁止放置,行列数从1开始。
输出格式
输出一个整数,表示结果。
数据范围
1≤N≤100
输出样例:
8 0
输出样例:
32
算法1
棋盘的格子分为黑白两种属性,那么一个骨牌如果能放置在棋盘上,必然覆盖的是一个黑格子一个白格子
将黑白格子看做点,每个骨牌看作为边,那么就是一个二分图最大匹配
C++ 代码
// 1231324.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cstring>
using namespace std;
int n, m;
const int N = 110;
bool g[N][N];
bool st[N][N];
pair<int, int> match[N][N];
/*
1≤N≤100
输出样例:
8 0
输出样例:
32
*/
int addx[4] = { 1,0,-1,0 };
int addy[4] = { 0,1,0,-1 };
bool find(int x, int y)
{
for (int i = 0; i < 4; i++) {
int newx = x + addx[i];
int newy = y + addy[i];
if (newx >=1 && newx <= n && newy>=1 && newy <= n &&
g[newx][newy] == false &&st[newx][newy] == false)
{
st[newx][newy] = true;
if (match[newx][newy].first == -1 ||
find(match[newx][newy].first, match[newx][newy].second))
{
match[newx][newy] = { x,y };
return true;
}
}
}
return false;
}
int main()
{
cin >> n >> m;
while (m--) {
int a, b;
cin >> a >> b;
g[a][b] = true;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
match[i][j].first = -1;
match[i][j].second = -1;
}
}
int res = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
//偶点 并且 该点无障碍
if ((i + j) % 2 == 1 && g[i][j] == false) {
memset(st, 0, sizeof st);
if (find(i, j)) res++;
}
}
}
cout << res << endl;
return 0;
}