bzoj3175【TJOI2013】攻击装置

3175: [Tjoi2013]攻击装置

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 839   Solved: 418
[ Submit][ Status][ Discuss]

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




二分图最大点独立集裸题




#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 40005
using namespace std;
int n,cnt,ans,head[maxn],match[maxn];
int dx[8]={-1,-2,1,2,-1,-2,1,2},dy[8]={-2,-1,-2,-1,2,1,2,1};
bool f[205][205],vst[maxn];
char s[205];
struct edge_type{int next,to;}e[maxn*8];
inline int num(int x,int y)
{
	return (x-1)*n+y;
}
inline void add_edge(int x,int y)
{
	e[++cnt]=(edge_type){head[x],y};
	head[x]=cnt;
}
inline bool dfs(int x)
{
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (!vst[y])
		{
			vst[y]=true;
			if (!match[y]||dfs(match[y]))
			{
				match[y]=x;
				return true;
			}
		}
	}
	return false;
}
int main()
{
	scanf("%d",&n);
	F(i,1,n)
	{
		scanf("%s",s+1);
		F(j,1,n) f[i][j]=s[j]=='0';
	}
	F(i,1,n) F(j,1,n) if (f[i][j]&&(i+j)%2) F(k,0,7)
	{
		int x=i+dx[k],y=j+dy[k];
		if (x<1||y<1||x>n||y>n) continue;
		if (!f[x][y]) continue;
		add_edge(num(i,j),num(x,y));
	}
	F(i,1,n) F(j,1,n) if (f[i][j]) ans++;
	F(i,1,n) F(j,1,n) if (f[i][j]&&(i+j)%2)
	{
		memset(vst,false,sizeof(vst));
		if (dfs(num(i,j))) ans--;
	}
	printf("%d\n",ans);
	return 0;
}


你可能感兴趣的:(二分图,bzoj)