题目描述
在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入
对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击
输入格式
第一行有 2 个正整数n 和 m (1<=n<=200, 0<=m<n2),分别表示棋盘的大小和障碍数。接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。
输出格式
将计算出的共存骑士数输出
题解:
和P4304 [TJOI2013]攻击装置类似的题,这里懒得写了,双倍经验
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define LL long long
const int MAXN = 40000+50;
const int MAXM = 2e6+50;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
int n,m,s,t,tot=1,head[MAXN],to[MAXM],nxt[MAXM],w[MAXM],h[MAXN],a[205][205];
int dir[][2]={{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,1},{-2,-1}};
inline void ade(int u,int v,int ww){
to[++tot]=v; w[tot]=ww; nxt[tot]=head[u]; head[u]=tot;
}
inline void add(int u,int v,int w){ ade(u,v,w); ade(v,u,0); }
inline int bfs(){
queue<int> que; que.push(s); memset(h,0,sizeof(h)); h[s]=1;
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u];i;i=nxt[i]){
if(w[i] && !h[to[i]]){
h[to[i]]=h[u]+1; que.push(to[i]);
}
}
}
return h[t];
}
inline int dfs(int x,int f){
if(x==t) return f; int fl=0;
for(int i=head[x];i&&f;i=nxt[i]){
if(w[i] && h[to[i]]==h[x]+1){
int mi=dfs(to[i],min(f,w[i]));
w[i]-=mi; w[i^1]+=mi; fl+=mi; f-=mi;
}
}
if(!fl) h[x]=-1;
return fl;
}
inline int dinic(){
int res=0;
while(bfs()) res+=dfs(s,INF);
return res;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d%d",&n,&m); s=0,t=n*n+1;
for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),a[x][y]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]) continue;
if((i+j)&1) add(s,(i-1)*n+j,1);
else add((i-1)*n+j,t,1);
if((i+j)&1){
for(int k=0;k<8;k++){
int x=i+dir[k][0],y=j+dir[k][1];
if(x<1 || x>n || y<1 || y>n || a[x][y]==1) continue;
add((i-1)*n+j,(x-1)*n+y,1);
}
}
}
}
printf("%d\n",n*n-m-dinic());
return 0;
}
来源:CSDN
作者:Nightmare丶
链接:https://blog.csdn.net/qq_43544481/article/details/104107096