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
题解
我就说我不会黑白染色yy的做法怎么过不去。。。
黑白染色,相邻点染不同的颜色
然后你会发现不能一起被选中的点其实都是异色
st向白色连边,流量1
黑色向ed连边,流量1
不能同时选中的点连起来,流量INF
输出sum-最小割即可
bzoj3175
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[8]={-2,-1,1,2,2,1,-1,-2};
const int dy[8]={-1,-2,-2,-1,1,2,2,1};
struct node
{
int x,y,c,next,other;
}a[410000];int len,last[51000];
void ins(int x,int y,int c)
{
int k1,k2;
k1=++len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
k2=++len;
a[len].x=y;a[len].y=x;a[len].c=0;
a[len].next=last[y];last[y]=len;
a[k1].other=k2;
a[k2].other=k1;
}
int list[211000],h[51000];
int head,tail,st,ed;
bool bt_h()
{
list[1]=st;head=1;tail=2;
memset(h,0,sizeof(h));
h[st]=1;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>0 && h[y]==0)
{
h[y]=h[x]+1;
list[tail++]=y;
}
}
head++;
}
if(h[ed]==0)return false;
return true;
}
int findflow(int x,int f)
{
if(x==ed)return f;
int s=0,t;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]==h[x]+1 && a[k].c>0 && s<f)
{
s+=(t=findflow(y,min(a[k].c,f-s)));
a[k].c-=t;a[a[k].other].c+=t;
}
}
if(s==0)h[x]=0;
return s;
}
int n;
char mp[210][210];
int col[210][210];
int pt(int x,int y){return (x-1)*n+y;}
int main()
{
scanf("%d",&n);st=n*n+1;ed=n*n+2;
for(int i=1;i<=n;i++)scanf("%s",mp[i]+1);
int sum=0;
memset(col,0,sizeof(col));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(j==1)col[i][j]=col[i-1][j]^1;
else col[i][j]=col[i][j-1]^1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]=='0'){if(col[i][j]==0)ins(st,pt(i,j),1);else ins(pt(i,j),ed,1);sum++;}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]=='0' && col[i][j]==0)
{
for(int k=0;k<=7;k++)
{
int x=i+dx[k],y=j+dy[k];
if(x<1 || x>n || y<1 || y>n || mp[x][y]!='0')continue;
ins(pt(i,j),pt(x,y),999999999);
}
}
int ans=0;
while(bt_h())ans+=findflow(st,999999999);
printf("%d\n",sum-ans);
return 0;
}
bzoj4808
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[8]={-2,-1,1,2,2,1,-1,-2};
const int dy[8]={-1,-2,-2,-1,1,2,2,1};
struct node
{
int x,y,c,next,other;
}a[410000];int len,last[51000];
void ins(int x,int y,int c)
{
int k1,k2;
k1=++len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
k2=++len;
a[len].x=y;a[len].y=x;a[len].c=0;
a[len].next=last[y];last[y]=len;
a[k1].other=k2;
a[k2].other=k1;
}
int list[211000],h[51000];
int head,tail,st,ed;
bool bt_h()
{
list[1]=st;head=1;tail=2;
memset(h,0,sizeof(h));
h[st]=1;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>0 && h[y]==0)
{
h[y]=h[x]+1;
list[tail++]=y;
}
}
head++;
}
if(h[ed]==0)return false;
return true;
}
int findflow(int x,int f)
{
if(x==ed)return f;
int s=0,t;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]==h[x]+1 && a[k].c>0 && s<f)
{
s+=(t=findflow(y,min(a[k].c,f-s)));
a[k].c-=t;a[a[k].other].c+=t;
}
}
if(s==0)h[x]=0;
return s;
}
int n,m;
int mp[210][210];
int col[210][210];
int pt(int x,int y){return (x-1)*m+y;}
int main()
{
scanf("%d%d",&n,&m);st=n*m+1;ed=n*m+2;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)scanf("%d",&mp[i][j]);
int sum=0;
memset(col,0,sizeof(col));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(j==1)col[i][j]=col[i-1][j]^1;
else col[i][j]=col[i][j-1]^1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]==0){if(col[i][j]==0)ins(st,pt(i,j),1);else ins(pt(i,j),ed,1);sum++;}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]==0 && col[i][j]==0)
{
for(int k=0;k<=7;k++)
{
int x=i+dx[k],y=j+dy[k];
if(x<1 || x>n || y<1 || y>m || mp[x][y]!=0)continue;
ins(pt(i,j),pt(x,y),999999999);
}
}
int ans=0;
while(bt_h())ans+=findflow(st,999999999);
printf("%d\n",sum-ans);
return 0;
}