AcWing 378. 骑士放置 题解

原题链接

题目描述

给定一个 N*M 的棋盘,有一些格子禁止放棋子。

问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的“骑士”,类似于中国象棋的“马”,按照“日”字攻击,但没有中国象棋“别马腿”的规则)。

样例

输入样例
2 3 0

输出样例
4

(二分图——最大独立集) O ( n ∗ m ) O(n*m) O(nm)

思路:通过涂色法(棋子位置和除棋子可到位置变黑色,其余不变)发现,黑色与白色有公共边,即可使用二分图求解

时间复杂度

O ( n ∗ m ) O(n*m) O(nm)

参考文献

y总的课+《算法竞赛进阶指南》

C++ 代码

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int maxn=110;
PII match[maxn][maxn];
bool g[maxn][maxn];
int n,m,t,x,y,res;
bool st[maxn][maxn];
int fx[]={-2,-1,1,2,2,1,-1,-2};
int fy[]={1,2,2,1,-1,-2,-2,-1};
bool find(int x,int y){
	for(int i=0;i<8;i++){
	    int a=x+fx[i];
	    int b=y+fy[i];
	    if(a<1||a>n||b<1||b>m)continue;
	    if(g[a][b]||st[a][b])continue;
	    st[a][b]=true;
	    PII t=match[a][b];
	    if(t.x==0||find(t.x,t.y)){
	        match[a][b]={x,y};
	        return true;
	    }
	}
	return false;
}
int main(){
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=t;i++){
        scanf("%d%d",&x,&y);
    	g[x][y]=true;
    }
	for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    	    if((i+j)%2||g[i][j])continue;
    	    memset(st,false,sizeof st);
			if(find(i,j)){
				res++;
			}
		}
	}
	cout<<n*m-res-t;
    return 0;
}
posted @   小罐猹  阅读(118)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法
点击右上角即可分享
微信分享提示