【bzoj3175】【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

题解:显然题目要求二分图最大独立集。

代码:

 
#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;
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值