在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入
对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击
和方格取数一模一样
只不过相邻改成了日字 所有的权值都为1
主要要减去m个障碍
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f const int N=4e5+44; const int M=4e6+54; struct edge { int to, next, w; } e[M << 1]; int head[N], cnt = 1; void add(int x, int y, int z) { e[++cnt] = (edge){y, head[x], z}; head[x] = cnt; e[++cnt] = (edge){x, head[y], 0}; head[y] = cnt; } int level[N]; bool bfs(int s, int t) { memset(level, 0, sizeof level); queue<int> q; level[s] = 1; q.push(s); while (!q.empty()) { int pos = q.front(); q.pop(); for (int i = head[pos]; i; i = e[i].next) { int nx = e[i].to; if (!e[i].w || level[nx]) continue; level[nx] = level[pos] + 1; q.push(nx); } } return level[t]; } int dfs(int s, int t, int flow) { if (s == t) return flow; int ret = 0; for (int i = head[s]; flow && i; i = e[i].next) { int nx = e[i].to; if (level[nx] == level[s] + 1 && e[i].w) { int tmp = dfs(nx, t, min(flow, e[i].w)); e[i].w -= tmp; e[i ^ 1].w += tmp; flow -= tmp; ret += tmp; } } if (!ret) level[s] = 0; return ret; } int dinic(int s, int t) { int ret = 0; while (bfs(s, t)) ret += dfs(s, t, inf); return ret; } int n,m,s,t; int id(int x,int y) { return (x-1)*n+y+3; } int mp[205][205]; int dx[]={1,1,-1,-1,2,2,-2,-2}; int dy[]={2,-2,2,-2,1,-1,1,-1}; int main() { s=1;t=2; RII(n,m); rep(i,1,m) { int a,b;RII(a,b);mp[a][b]=1; } rep(i,1,n) rep(j,1,n) if(!mp[i][j]) { if((i+j)&1) { add(s,id(i,j),1); rep(k,0,7) { int x=i+dx[k],y=j+dy[k]; if(x>=1&&x<=n&&y>=1&&y<=n&&mp[x][y]!=1) { add(id(i,j),id(x,y),1); } } } else add(id(i,j),t,1); } cout<<n*n-m-dinic(s,t); }
也可以用二分图匹配来做 但是 会T一些点 (只是介绍思路)
求的是最大独立集团点数 = n - 最大匹配数!
#include <bits/stdc++.h> using namespace std; const int N = 206; const int dx[8] = {-2,-2,-1,-1,1,1,2,2}; const int dy[8] = {-1,1,-2,2,-2,2,-1,1}; int n, m, ans, f[N][N][2]; bool a[N][N], v[N][N]; inline bool dfs(int x, int y) { for (int i = 0; i < 8; i++) { int nx = x + dx[i], ny = y + dy[i]; if (nx < 1 || ny < 1 || nx > n || ny > n) continue; if (a[nx][ny] || v[nx][ny]) continue; v[nx][ny] = 1; if (!f[nx][ny][0] || dfs(f[nx][ny][0], f[nx][ny][1])) { f[nx][ny][0] = x; f[nx][ny][1] = y; return 1; } } return 0; } int main() { cin >> n >> m; for (int i = 1; i <= m; i++) { int x, y; scanf("%d %d", &x, &y); a[x][y] = 1; } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { if (((i ^ j) & 1) || a[i][j]) continue; memset(v, 0, sizeof(v)); ans += dfs(i, j); } cout << n * n - m - ans << endl; return 0; }