Link
Diffculty
算法难度6,思维难度5,代码难度6
Description
给定一个 n × m n\times m n×m 的地图,有空地,障碍,不能放炸弹的空地。
炸弹的威力不能穿过障碍,可以穿过不能放炸弹的空地。
要求放最多的炸弹,使得不存在炸弹能互相炸到。
1 ≤ n , m ≤ 50 1\le n,m\le 50 1≤n,m≤50
Solution
考虑取出行列中的极长连续不含障碍的段。
然后对于每个可以放炸弹的空地,变成一条边,从行点连向列点。
跑最大流即可。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f==1?x:-x;
}
const int N=55,M=1e4+5;
int cnt,s,t,tot=-1,head[M],to[M],Next[M],flow[M];
inline void addedge(int x,int y,int l){
to[++tot]=y;Next[tot]=head[x];head[x]=tot;flow[tot]=l;
to[++tot]=x;Next[tot]=head[y];head[y]=tot;flow[tot]=0;
}
int d[M],q[M],cur[M];
inline bool bfs(){
for(int i=0;i<=cnt;++i)d[i]=1e9;
int l=1,r=1;q[1]=s;d[s]=0;
while(l<=r){
int x=q[l++];
for(int i=head[x];~i;i=Next[i]){
int u=to[i];
if(flow[i] && d[u]>d[x]+1){
d[u]=d[x]+1;
q[++r]=u;
}
}
}
return d[t]<(int)1e9;
}
inline int dfs(int x,int a){
if(x==t || !a)return a;
int F=0,f;
for(int &i=cur[x];~i;i=Next[i]){
int u=to[i];
if(flow[i] && d[u]==d[x]+1 && (f=dfs(u,min(a,flow[i])))>0){
flow[i]-=f;
flow[i^1]+=f;
F+=f;
a-=f;
if(!a)return F;
}
}
return F;
}
inline int dinic(){
int F=0;
while(bfs()){
for(int i=0;i<=cnt;++i)cur[i]=head[i];
F+=dfs(s,1e9);
}
return F;
}
int n,m,turn[200];
int id1[N][N],id2[N][N],a[N][N];
char ch[N];
int main(){
memset(head,-1,sizeof head);
turn['*']=0;turn['x']=1;turn['#']=2;
n=read();m=read();s=0;
for(int i=1;i<=n;++i){
scanf("%s",ch+1);
for(int j=1;j<=m;++j)a[i][j]=turn[(int)ch[j]];
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(a[i][j]==2)continue;
if(j==1 || a[i][j-1]==2)id1[i][j]=++cnt;
else id1[i][j]=id1[i][j-1];
}
}
int cnt1=cnt;
for(int i=1;i<=m;++i){
for(int j=1;j<=n;++j){
if(a[j][i]==2)continue;
if(j==1 || a[j-1][i]==2)id2[j][i]=++cnt;
else id2[j][i]=id2[j-1][i];
}
}
t=++cnt;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(a[i][j]==0)
addedge(id1[i][j],id2[i][j],1);
for(int i=1;i<=cnt1;++i)addedge(s,i,1);
for(int i=cnt1+1;i<=cnt;++i)addedge(i,t,1);
printf("%d\n",dinic());
return 0;
}