【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类,就是一个二分图,然后能攻击的连边跑匈牙利。

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 #define Maxn 210
 8 
 9 struct node
10 {
11     int x,y,next;
12 }t[Maxn*Maxn*10];
13 int len,first[Maxn*Maxn];
14 
15 void ins(int x,int y)
16 {
17     t[++len].x=x;t[len].y=y;
18     t[len].next=first[x];first[x]=len;
19 }
20 
21 int num[Maxn][Maxn];
22 char s[Maxn];
23 
24 int bx[10]={0,-1,-2,1,2,-1,-2,1,2},
25     by[10]={0,-2,-1,-2,-1,2,1,2,1};
26 //(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)
27 
28 int xx[Maxn*Maxn],chw[Maxn*Maxn],match[Maxn*Maxn];
29 
30 bool ffind(int x,int nt)
31 {
32     for(int i=first[x];i;i=t[i].next) if(chw[t[i].y]!=nt)
33     {
34         int y=t[i].y;
35         chw[y]=nt;
36         if(match[y]==0||ffind(match[y],nt))
37         {
38             match[y]=x;
39             return 1;
40         }
41     }
42     return 0;
43 }
44 
45 
46 int get_ans()
47 {
48     memset(match,0,sizeof(match));
49     memset(chw,0,sizeof(chw));
50     int nt=0,ans=0;
51     for(int i=1;i<=xx[0];i++)
52     {
53         nt++;
54         if(ffind(xx[i],nt)) ans++;
55     }
56     return ans;
57 }
58 
59 int main()
60 {
61     int n;
62     scanf("%d",&n);
63     int h=0;
64     memset(num,0,sizeof(num));
65     for(int i=1;i<=n;i++)
66     {
67         scanf("%s",s);
68         for(int j=0;j<n;j++)
69         {
70             if(s[j]=='0') num[i][j+1]=++h;
71         }
72     }
73     len=0;
74     memset(first,0,sizeof(first));
75     xx[0]=0;
76     for(int i=1;i<=n;i++)
77      for(int j=1;j<=n;j++) if(num[i][j]!=0&&(i+j)%2==0)
78      {
79          for(int k=1;k<=8;k++)
80          {
81              int nx=i+bx[k],ny=j+by[k];
82              if(nx<1||nx>n||ny<1||ny>n) continue;
83              if(num[nx][ny]==0) continue;
84              ins(num[i][j],num[nx][ny]);
85          }
86          xx[++xx[0]]=num[i][j];
87      }
88      int ans=get_ans();
89      printf("%d\n",h-ans);
90     return 0;
91 }
View Code

 

2017-02-22 13:22:40

posted @ 2017-02-22 13:16  konjak魔芋  阅读(193)  评论(0编辑  收藏  举报