AcWing 378. 骑士放置 题解

3 篇文章 0 订阅

原题链接

题目描述

给定一个 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值