372. 棋盘覆盖

题目链接

372. 棋盘覆盖

给定一个 \(N\)\(N\) 列的棋盘,已知某些格子禁止放置。

求最多能往棋盘上放多少块的长度为 \(2\)、宽度为 \(1\) 的骨牌,骨牌的边界与格线重合(骨牌占用两个格子),并且任意两张骨牌都不重叠。

输入格式

第一行包含两个整数 \(N\)\(t\),其中 \(t\) 为禁止放置的格子的数量。

接下来 \(t\) 行每行包含两个整数 \(x\)\(y\),表示位于第 \(x\) 行第 \(y\) 列的格子禁止放置,行列数从 \(1\) 开始。

输出格式

输出一个整数,表示结果。

数据范围

\(1 \le N \le 100\),
\(0 \le t \le 100\)

输入样例:

8 0

输出样例:

32

解题思路

匈牙利算法

这样的图很容易构造成一个二分图,即对于所有 \((i,j)\) 的格子,如果 \((i+j)\%2=0\) 的话则染为白色,否则染为黑色
除去障碍物,任意两个连续的方块之间连边,本质上就是要求出点不重复的最多边数,即二分图的最大匹配,用匈牙利算法求解即可

  • 时间复杂度:\(O(n^4)\)

代码

// Problem: 棋盘覆盖
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/374/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=105;
int n,t;
bool g[N][N],st[N][N];
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
PII match[N][N];
bool find(int x,int y)
{
	for(int i=0;i<4;i++)
	{
		int nx=x+dx[i],ny=y+dy[i];
		if(nx<1||nx>n||ny<1||ny>n||g[nx][ny])continue;
		if(!st[nx][ny])
		{
			st[nx][ny]=true;
			if(match[nx][ny].fi==0&&match[nx][ny].se==0||find(nx,ny))
			{
				match[nx][ny]={x,y};
				return true;
			}
		}
	}
	return false;
}
int main()
{
    scanf("%d%d",&n,&t);
    for(int i=1;i<=t;i++)
    {
    	int x,y;
    	scanf("%d%d",&x,&y);
    	g[x][y]=true;
    }
    int res=0;
    for(int i=1;i<=n;i++)
    	for(int j=1;j<=n;j++)
    	{
    		if((i+j)%2==0||g[i][j])continue;
    		memset(st,0,sizeof st);
    		if(find(i,j))res++;
    	}
    printf("%d",res);
    return 0;
}
posted @ 2022-11-29 16:10  zyy2001  阅读(28)  评论(0编辑  收藏  举报