版权声明:虽然我很菜,不过转载请标明出处。 https://blog.csdn.net/Patrickpwq/article/details/86653025
很显然柱子的高度就是边的容量 因为这个定义和容量很像
所以把柱子拆成两个点
然后之后就很显然了
源点先连接蜥蜴所在柱子上 容量为1 然后柱子之间符合距离要求的相连(注意是右端点连上左端点) 容量随意 然后能出去的柱子连汇点 容量随意
然后注意细节
#include<bits/stdc++.h>
const int N=100005;
const int INF=0x3f3f3f3f;
using namespace std;
int r,c,d,cnt1,cnt2;
int s,t;
struct Data
{
int x,y,h,pos;
}st[N],l[N];
inline int dis(Data L,Data S){ return (L.x-S.x)*(L.x-S.x)+(L.y-S.y)*(L.y-S.y); }
int first[2*N],tot=1;
struct Edge
{
int to,next,cap;
}edge[2*N];
inline void addedge(int x,int y,int z)
{
tot++;
edge[tot].to=y; edge[tot].next=first[x]; edge[tot].cap=z; first[x]=tot;
}
int step[2*N],cur[2*N];
bool bfs()
{
memset(step,-1,sizeof(step));
queue <int> q;
q.push(s); step[s]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
for(int u=first[now];u;u=edge[u].next)
{
int vis=edge[u].to;
if(edge[u].cap>0&&step[vis]==-1)
{
step[vis]=step[now]+1;
q.push(vis);
if(vis==t) return 1;
}
}
}
return 0;
}
int dfs(int now,int f)
{
if(now==t||!f) return f;
int out=0;
for(int &u=cur[now];u;u=edge[u].next)
{
int vis=edge[u].to;
if(edge[u].cap&&step[vis]==step[now]+1)
{
int w=dfs(vis,min(f,edge[u].cap));
if(!w) continue;
f-=w; out+=w;
edge[u].cap-=w; edge[u^1].cap+=w;
if(!f) break;
}
}
return out;
}
void Maxflow()
{
int ans=0;
while(bfs())
{
for(int i=1;i<=t;i++) cur[i]=first[i];
ans+=dfs(s,INF);
}
cout<<cnt2-ans<<endl;
}
int main()
{
cin>>r>>c>>d;
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
char x;
cin>>x;
x=x-'0';
if(x>0) st[++cnt1].x=i,st[cnt1].y=j,st[cnt1].h=x;
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
char x;
cin>>x;
if(x=='L') l[++cnt2].x=i,l[cnt2].y=j;
}
s=1; t=1+2*cnt1+1;
for(int i=1;i<=cnt1;i++) //石柱与石柱相连
{
for(int j=1;j<=cnt1;j++)
{
if(i==j) continue;
if(dis(st[i],st[j])>d*d) continue;
addedge(1+i+cnt1,1+j,INF); //右端朝左端连边
addedge(1+j,1+i+cnt1,0);
}
}
for(int i=1;i<=cnt2;i++) //枚举蜥蜴所在编号
{
for(int j=1;j<=cnt1;j++) //哪个石头和它是一样的
{
if(l[i].x==st[j].x&&l[i].y==st[j].y)
{
l[i].pos=j;
break;
}
}
}
for(int i=1;i<=cnt2;i++) //源点与蜥蜴所在石柱
{
addedge(s,1+l[i].pos,1);
addedge(1+l[i].pos,s,0);
}
for(int i=1;i<=cnt1;i++) //石柱左右端点
{
addedge(1+i,1+i+cnt1,st[i].h);
addedge(1+i+cnt1,1+i,0);
}
for(int i=1;i<=cnt1;i++) //可以跳出去
{
int R,C;
R=st[i].x; C=st[i].y;
if(R<=d||R+d>r||C<=d||C+d>c)
{
addedge(1+cnt1+i,t,INF);
addedge(t,1+cnt1+i,0);
}
}
Maxflow();
return 0;
}