首页 > 代码库 > 【vijos】1729 Knights(匈牙利)
【vijos】1729 Knights(匈牙利)
https://vijos.org/p/1729
这题好奇葩,为嘛N开到30就会re啊。。。。。。。。。。n<=26吗。。。。
sad
因为根据棋子的分布,能攻击的一定各在一黑白格上,所以直接二分图了。
(但是我想了想,如果不是黑白格的,怎么做。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#include <cstdio>#include <cstring>#include <cmath>#include <string>#include <iostream>#include <algorithm>#include <queue>using namespace std;#define rep(i, n) for(int i=0; i<(n); ++i)#define for1(i,a,n) for(int i=(a);i<=(n);++i)#define for2(i,a,n) for(int i=(a);i<(n);++i)#define for3(i,a,n) for(int i=(a);i>=(n);--i)#define for4(i,a,n) for(int i=(a);i>(n);--i)#define CC(i,a) memset(i,a,sizeof(i))#define read(a) a=getint()#define print(a) printf("%d", a)#define dbg(x) cout << (#x) << " = " << (x) << endl#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }#define printarr1(a, b) for1(_, 1, b) cout << a[_] << ‘\t‘; cout << endlinline const int getint() { int r=0, k=1; char c=getchar(); for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) r=r*10+c-‘0‘; return k*r; }inline const int max(const int &a, const int &b) { return a>b?a:b; }inline const int min(const int &a, const int &b) { return a<b?a:b; }const int N=50;int ihead[N*N], cnt, ly[N*N], n, m, vis[N][N], ans, ins[N*N];const int dx[]={-1, -2, -2, -1, 1, 2, 2, 1}, dy[]={-2, -1, 1, 2, 2, 1, -1, -2};struct ED { int next, to; }e[(N*N)<<1];struct dat{ int x, y; }a[N*N];void add(int u, int v) { e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;}bool ifind(int x) { int y; for(int i=ihead[x]; i; i=e[i].next) if(!ins[y=e[i].to]) { ins[y]=1; if(!ly[y] || ifind(ly[y])) { ly[y]=x; return true; } } return false;}int main() { read(n); read(m); char s[10]; for1(i, 1, m) { scanf("%s", s+1); a[i].x=s[1]-‘A‘+1; int len=strlen(s+1); for1(j, 2, len) { a[i].y*=10; a[i].y+=s[j]-‘0‘; } vis[a[i].x][a[i].y]=i; } for1(i, 1, m) { rep(k, 8) { int fx=dx[k]+a[i].x, fy=dy[k]+a[i].y; if(fx<1 || fy<1 || fx>n || fy>n || !vis[fx][fy]) continue; add(i, vis[fx][fy]); } } for1(i, 1, m) if((a[i].x+a[i].y)&1) { CC(ins, 0); if(ifind(i)) ++ans; } printf("%d\n", ans); return 0;}
描述
在一个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 9A1A5B3C5C1D2D4E6F5
样例输出1[复制]
3
限制
每个测试点1s
提示
30%的数据满足,1 <= N <= 4.
100%的数据满足,1 <= N <= 26,骑士的坐标格式均合法,任意两个骑士的位置都不同。
来源
Topcoder
【vijos】1729 Knights(匈牙利)