vijos p1729——Knights

描述

在一个N*N的正方形棋盘上,放置了一些骑士。我们将棋盘的行用1开始的N个自然数标记,将列用'A'开始的N个大写英文字母标记。举个例子来说,一个标准的8*8的国际象棋棋盘的行标记为1..8,列标记为A..H,D3、H1分别表示棋盘上第3行第4列和第1行第8列的格子。

骑士是这样一类棋子。若一个骑士放置在格子(x, y)。那么格子(x-2, y-1), (x-2, y+1), (x-1, y-2), (x-1, y+2), (x+1, y-2), (x+1, y+2), (x+2, y-1), (x+2, y+1)如果在棋盘内的话,就都处于这个骑士的攻击范围内。

如果若干个骑士在棋盘上的一种放置方法能使得没有一个骑士处在其它骑士的攻击范围内,那么称为和谐的方案。现在给定一个棋盘,上面已经放置了M个骑士。你的任务是拿走尽可能少的骑士,使得剩余的骑士构成一个和谐的方案。

格式

输入格式

第一行,两个正整数N,M,分别表示棋盘的大小,和骑士的数目。

以下M行,每行一个字符串,描述一个骑士的坐标。

输出格式

输出一行,一个整数,表示至少拿走多少个骑士。

样例1

样例输入1

6 9
A1
A5
B3
C5
C1
D2
D4
E6
F5

样例输出1

3

限制

每个测试点1s

提示

30%的数据满足,1 <= N <= 4.
100%的数据满足,1 <= N <= 26,骑士的坐标格式均合法,任意两个骑士的位置都不同。

由数据可以看出,矛盾的两个骑士横纵坐标和为1奇1偶,则可以将横纵坐标之和为偶数的所有骑士的集合定义为x点集,为奇数的所有骑士的集合定义为y点集。

将矛盾的骑士全部建边,匈牙利算法找坐标和为偶数的所有匹配,得到的最大匹配就是要去掉的数。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=900;
 4 int _map[maxn][maxn];
 5 int match[maxn];
 6 int vis[maxn];
 7 bool exist[maxn];
 8 bool pd[maxn];
 9 int n,m;
10 struct node{
11     int x,y;
12 }a[maxn];
13 inline void gg()
14 {
15     scanf("%d%d",&n,&m);
16     for(int i=1;i<=m;i++)
17     {
18         char c=getchar();
19         while(c<'A'||c>'Z')c=getchar();
20         a[i].y=c-'A'+1;
21         scanf("%d",&a[i].x);
22         if((a[i].x+a[i].y)%2==0)
23         pd[i]=true;
24     }
25     for(int i=1;i<=m;i++)
26     for(int j=1;j<=m;j++)
27     {
28         if(pd[i]==true&&pd[j]==false)//true的为x结点 
29         {
30             if(abs(a[i].x-a[j].x)==1&&abs(a[i].y-a[j].y)==2)
31             _map[i][j]=true;
32             if(abs(a[i].x-a[j].x)==2&&abs(a[i].y-a[j].y)==1)
33             _map[i][j]=true;
34         }
35         if(pd[i]==false&&pd[j]==true)
36         {
37             if(abs(a[i].x-a[j].x)==1&&abs(a[i].y-a[j].y)==2)
38             _map[j][i]=true;
39             if(abs(a[i].x-a[j].x)==2&&abs(a[i].y-a[j].y)==1)
40             _map[j][i]=true;
41         }
42     }
43     return ;
44 }
45 bool dfs(int x)
46 {
47     for(int i=1;i<=m;i++)
48     {
49         if(_map[x][i]&&vis[i]==false)
50         {
51             vis[i]=true;
52             if(match[i]==-1||dfs(match[i]))
53             {
54                 match[i]=x;
55                 return true;
56             }
57         }
58     }
59     return false;
60 }
61 inline void hungary()
62 {
63     int count=0;
64     memset(match,-1,sizeof(match));
65     for(int i=1;i<=m;i++)
66     if(pd[i]==true)
67     {
68         memset(vis,false,sizeof(vis));
69         if(dfs(i))count++;
70     }
71     printf("%d",count);
72     return ;
73 }
74 int main()
75 {
76     gg();
77     hungary();
78     return 0;
79 }
原文地址:https://www.cnblogs.com/937337156Zhang/p/6048317.html