P3355 骑士共存问题

﹥>﹥吖頭↗ 提交于 2020-01-29 20:35:14

题目描述

在一个 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;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!