【BZOJ 3175】 3175: [Tjoi2013]攻击装置(二分图匹配)

时间:2023-03-09 13:34:11
【BZOJ 3175】 3175: [Tjoi2013]攻击装置(二分图匹配)

3175: [Tjoi2013]攻击装置

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

Sample Output

4

HINT

100%数据 N<=200

Source

【分析】

  以坐标和的奇偶分成2类,就是一个二分图,然后能攻击的连边跑匈牙利。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 210 struct node
{
int x,y,next;
}t[Maxn*Maxn*];
int len,first[Maxn*Maxn]; void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
} int num[Maxn][Maxn];
char s[Maxn]; int bx[]={,-,-,,,-,-,,},
by[]={,-,-,-,-,,,,};
//(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) int xx[Maxn*Maxn],chw[Maxn*Maxn],match[Maxn*Maxn]; bool ffind(int x,int nt)
{
for(int i=first[x];i;i=t[i].next) if(chw[t[i].y]!=nt)
{
int y=t[i].y;
chw[y]=nt;
if(match[y]==||ffind(match[y],nt))
{
match[y]=x;
return ;
}
}
return ;
} int get_ans()
{
memset(match,,sizeof(match));
memset(chw,,sizeof(chw));
int nt=,ans=;
for(int i=;i<=xx[];i++)
{
nt++;
if(ffind(xx[i],nt)) ans++;
}
return ans;
} int main()
{
int n;
scanf("%d",&n);
int h=;
memset(num,,sizeof(num));
for(int i=;i<=n;i++)
{
scanf("%s",s);
for(int j=;j<n;j++)
{
if(s[j]=='') num[i][j+]=++h;
}
}
len=;
memset(first,,sizeof(first));
xx[]=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++) if(num[i][j]!=&&(i+j)%==)
{
for(int k=;k<=;k++)
{
int nx=i+bx[k],ny=j+by[k];
if(nx<||nx>n||ny<||ny>n) continue;
if(num[nx][ny]==) continue;
ins(num[i][j],num[nx][ny]);
}
xx[++xx[]]=num[i][j];
}
int ans=get_ans();
printf("%d\n",h-ans);
return ;
}

2017-02-22 13:22:40