返回顶部
大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

P3355 骑士共存问题

题目描述

在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入

对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击

输入格式

第一行有 2 个正整数n 和 m (1<=n<=200, 0<=m<n2),分别表示棋盘的大小和障碍数。接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。

输出格式

将计算出的共存骑士数输出

输入输出样例

输入 #1
3 2
1 1
3 3
输出 #1
5

黑白染色构图,能攻击到的就连一条inf的边,跑一遍最大流
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;

const int maxn = 200*201;

int dx[]={-2,-2,-1,1,2,2,1,-1},dy[]={-1,1,2,2,1,-1,-2,-2};

int n,m,head[maxn],size,cur[maxn],dep[maxn],s,t;

bool ok[220][220];

struct edge{
    int v,nex,flow;
}e[3000010*2];

void adde(int u,int v,int flow){
    e[size].v=v;e[size].nex=head[u];e[size].flow=flow;head[u]=size++;
}

bool bfs(){
    memset(dep,-1,sizeof(dep));
    dep[s]=0;queue<int> q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];~i;i=e[i].nex){
            int v=e[i].v;
            if(dep[v]==-1&&e[i].flow){
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
    return dep[t]!=-1;
}

int dfs(int u,int f){
    if(u==t) return f;
    int used=0;
    for(int& i=cur[u];~i;i=e[i].nex){
        int v=e[i].v;
        if(e[i].flow&&dep[v]==dep[u]+1){
            int d=dfs(v,min(e[i].flow,f-used));
            used+=d;e[i].flow-=d;e[i^1].flow+=d;
            if(used==f) break;
        }
    }
    return used;
}

int dinic(){
    int res=0;
    while(bfs()){
        for(int i=0;i<=n*n+1;i++) cur[i]=head[i];
        res+=dfs(s,inf); 
    }
    return res;
}

int main(){
//    freopen("in.txt","r",stdin);
    s=0;t=n*n+1;
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++) {
        int x,y;scanf("%d%d",&x,&y);
        ok[x][y]=1;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            if(ok[i][j]) continue;
            if((i+j)&1) {
                adde(s,(i-1)*n+j,1);adde((i-1)*n+j,s,0);
            }else {
                adde((i-1)*n+j,t,1);adde(t,(i-1)*n+j,0);
            }
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            if(((i+j)&1)==0) continue;//不要写成if((i+j)&1==0)
            for(int k=0;k<=7;k++){
                int ex=dx[k]+i,ey=dy[k]+j;
                if(ex>n||ex<1||ey>n||ey<1) continue;
                if(ok[ex][ey]) continue;
                adde((i-1)*n+j,(ex-1)*n+ey,inf);adde((ex-1)*n+ey,(i-1)*n+j,0);
            }
        }
    printf("%d",n*n-m-dinic());
}

 

posted @ 2019-09-02 09:20  plysc  阅读(178)  评论(0编辑  收藏  举报