#bzoj-Balic2001#棋盘上的骑士(Hungary)

来源:互联网 发布:淘宝店铺被处置 编辑:程序博客网 时间:2024/06/04 19:51

[Balic2001]棋盘上的骑士

时间限制: 10 Sec  内存限制: 64 MB

题目描述

一个N*N的棋盘上,有一些小方格被拿走了,不能放置骑士,其它位置可以放。现要在棋盘上放若干骑士,要求任一个骑士都不能在其他骑士的攻击点上。请算出棋盘上最多能有几个骑士。骑士攻击范围如图所示(S是骑士的位置,X表示马的攻击点) 

输入

第一行包含2个整数n和m,用单个的空格分开,1<=n<=200 , 0<=m < 40000;n 是国际象棋棋盘的大小,m是被拿走的格子数。 下面m行每行包含 2 个整数:x和y,用单个的空格分开,1<=x,y<=n,这些是被拿走的格子的坐标。 棋盘的左上角的坐标是(1,1),右下角是(n,n)。拿走的格子没有重复的。

输出

一个整数,它应该是能放在国际象棋棋盘上的互不攻击对方的马的最大的数量。

样例输入

3 21 13 3

样例输出

5

一道很坑的匈牙利匹配题,坑在搜索顺序上

首先建图,将下标奇偶性相同的格子看做一部,余下的看做另一部,根据象棋规则,必有X部向Y部连边的是非法状态(即两个位置不共存)

所以检查冲突匹配数,剩下的为答案

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>using namespace std; const int Max = 205; struct node{    int v, nxt;}edge[Max * Max << 3]; int N, T, cnt;int fir[Max * Max], match[Max * Max];int dd[8][2] = {{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}};bool vis[Max * Max], P[Max][Max]; void addedge(int a, int b){edge[++ cnt].v = b, edge[cnt].nxt = fir[a], fir[a] = cnt;} bool inarea(int a, int b){    if(a < 1 || b < 1 || a > N || b > N || P[a][b]) return 0;    return 1;} bool Hungary(int i){    for(int j = fir[i]; j; j = edge[j].nxt) if(!vis[edge[j].v]){        vis[edge[j].v] = 1;        if(! match[edge[j].v] || Hungary(match[edge[j].v])){            match[edge[j].v] = i;            return 1;        }    }    return 0;} int main(){    cnt = 1;    scanf("%d%d", &N,&T);    int Ans = N * N - T;    int x, y;    while(T --){        scanf("%d%d", &x, &y);        P[x][y] = 1;    }    for(int i = 1;i <= N; ++ i)        for(int j = 1; j <= N; ++ j)            if(! P[i][j] && (i & 1) == (j & 1)){                int p1 = (i - 1) * N + j;                for(int k = 0; k < 8; ++ k){                    int xx = i + dd[k][0], yy = j + dd[k][1];                    if(inarea(xx, yy)){                        int p2 = (xx - 1) * N + yy;                        addedge(p1, p2);                    }                }            }    for(int i = 1; i <= N; ++ i)        for(int j = 1; j <= N; ++ j)            if(! P[i][j] && (i & 1) == (j & 1)){                memset(vis, 0, sizeof(vis));                Ans -= Hungary((i - 1) * N + j);            }    printf("%d\n", Ans);    return 0;}


原创粉丝点击