骑士共存问题
«问题描述:
在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘
上某些方格设置了障碍,骑士不得进入。
«编程任务:
对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑
士,使得它们彼此互不攻击。
«数据输入:
由文件knight.in给出输入数据。第一行有2 个正整数n 和m (1<=n<=200, 0<=m<=n*n)<n2),< span="">
分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障
碍的方格坐标。
«结果输出:
将计算出的共存骑士数输出到文件knight.out。
输入文件示例 输出文件示例
knight.in
3 2
1 1
3 3
knight.out
5
二分图最大独立集,转化为二分图最大匹配,从而用最大流解决。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #include<vector> 7 using namespace std; 8 const int mx[9]={0,1,1,-1,-1,2,2,-2,-2}; 9 const int my[9]={0,2,-2,2,-2,1,-1,1,-1}; 10 const int mxn=42000; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();} 15 return x*f; 16 } 17 struct edge{int v,nxt,f;}e[mxn<<4]; 18 int hd[mxn],mct=1; 19 void add_edge(int u,int v,int f){ 20 e[++mct].v=v;e[mct].f=f;e[mct].nxt=hd[u];hd[u]=mct;return; 21 } 22 int n,m; 23 int S,T; 24 int d[mxn]; 25 int id[210][210]; 26 int mp[210][210]; 27 bool BFS(int s,int t){ 28 queue<int>q; 29 memset(d,0,sizeof d); 30 d[s]=1; 31 q.push(s); 32 while(!q.empty()){ 33 int u=q.front();q.pop(); 34 for(int i=hd[u];i;i=e[i].nxt){ 35 int v=e[i].v; 36 if(!d[v] && e[i].f){ 37 d[v]=d[u]+1; 38 q.push(v); 39 } 40 } 41 } 42 return d[t]; 43 } 44 int DFS(int u,int lim){ 45 if(u==T)return lim; 46 int tmp,f=0; 47 for(int i=hd[u];i;i=e[i].nxt){ 48 int v=e[i].v; 49 if(d[v]==d[u]+1 && e[i].f){ 50 tmp=DFS(v,min(lim,e[i].f)); 51 e[i].f-=tmp; 52 e[i^1].f+=tmp; 53 lim-=tmp; 54 f+=tmp; 55 if(!lim)return f; 56 } 57 } 58 d[u]=0; 59 return f; 60 } 61 inline int Dinic(){ 62 int res=0; 63 while(BFS(S,T))res+=DFS(S,1e9); 64 return res; 65 } 66 void solve(){ 67 int i,j; 68 for(i=1;i<=n;i++) 69 for(j=1;j<=n;j++) 70 id[i][j]=(i-1)*n+j; 71 for(i=1;i<=n;i++) 72 for(j=1;j<=n;j++){ 73 if(mp[i][j])continue; 74 if((i+j)%2==0)//白色 75 { 76 add_edge(S,id[i][j],1); 77 add_edge(id[i][j],S,0); 78 for(int k=1;k<=8;k++){ 79 int nx=i+mx[k],ny=j+my[k]; 80 if(nx<1 || nx>n || ny<1 || ny>n || mp[nx][ny])continue; 81 add_edge(id[i][j],id[nx][ny],1); 82 add_edge(id[nx][ny],id[i][j],0); 83 } 84 } 85 else{//黑色 86 add_edge(id[i][j],T,1); 87 add_edge(T,id[i][j],0); 88 } 89 } 90 return; 91 } 92 int main() 93 { 94 freopen("knight.in","r",stdin); 95 freopen("knight.out","w",stdout); 96 n=read();m=read(); 97 int i,j,u,v; 98 for(i=1;i<=m;i++){ 99 u=read();v=read(); 100 mp[u][v]=1;//标记障碍 101 } 102 S=0;T=n*n+1; 103 solve(); 104 105 int ans=Dinic(); 106 ans=n*n-m-ans; 107 printf("%d ",ans); 108 return 0; 109 }