AcWing 378. 骑士放置 题解
原题链接
题目描述
给定一个 N*M 的棋盘,有一些格子禁止放棋子。
问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的“骑士”,类似于中国象棋的“马”,按照“日”字攻击,但没有中国象棋“别马腿”的规则)。
样例
输入样例
2 3 0
输出样例
4
(二分图——最大独立集) O ( n ∗ m ) O(n*m) O(n∗m)
思路:通过涂色法(棋子位置和除棋子可到位置变黑色,其余不变)发现,黑色与白色有公共边,即可使用二分图求解
时间复杂度
O ( n ∗ m ) O(n*m) O(n∗m)
参考文献
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;
}
她透过我的血,看到了另一抹殷红
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法