Description
给定一个01矩阵,其中你可以在0的位置放置攻击装置。每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1)
求在装置互不攻击的情况下,最多可以放置多少个装置。
Input
第一行一个整数N,表示矩阵大小为N*N。接下来N行每一行一个长度N的01串,表示矩阵。
Output
一个整数,表示在装置互不攻击的情况下最多可以放置多少个装置。
Sample Input
3
010
000
100
010
000
100
Sample Output
4
HINT
100%数据 N<=200
题解:显然题目要求二分图最大独立集。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 210
using namespace std;
int point[N][N],next[N*N*N],cnt,n,m,be[N][N][4],ans,a[N][N],dx[20],dy[20],tot;
char ch[N];
bool f[N][N];
struct use{int x,y;}e[N*N*N];
void add(int x,int y,int xx,int yy){
next[++cnt]=point[x][y];point[x][y]=cnt;
e[cnt].x=xx;e[cnt].y=yy;
}
bool find(int x,int y){
if (x==0||y==0) return false;
for (int i=point[x][y];i;i=next[i])
if (!f[e[i].x][e[i].y]){
f[e[i].x][e[i].y]=1;//cout<<e[i].x<<' '<<e[i].y<<endl;
if (!be[e[i].x][e[i].y][1]||find(be[e[i].x][e[i].y][1],be[e[i].x][e[i].y][2])){
be[e[i].x][e[i].y][1]=x;be[e[i].x][e[i].y][2]=y;
return true;
}
}
return false;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%*c%s",&ch);
for (int j=0;j<strlen(ch);j++){a[i][j+1]=ch[j]-'0';}
}
dx[1]=-1;dx[2]=-2;dx[3]=1;dx[4]=2;dx[5]=-1;dx[6]=-2;dx[7]=1;dx[8]=2;
dy[1]=-2;dy[2]=-1;dy[3]=-2;dy[4]=-1;dy[5]=2;dy[6]=1;dy[7]=2;dy[8]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]==0){
tot++;
for (int k=1;k<=8;k++){
int x=i+dx[k],y=j+dy[k];
if (x>=1&&x<=n&&y>=1&&y<=n&&a[x][y]!=1) add(i,j,x,y);
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]!=1){
memset(f,0,sizeof(f));
if (find(i,j)) ans++;
}
cout<<tot-ans/2<<endl;
}