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  阅读(93)  评论(0)    收藏  举报