调了一上午没调过样例TAT......
上机时间到了,只能求助dalao们帮助一下了(卑微)
代码中注释已加。
目前已知的是:快读没错,链式存图没错,dinic部分没错(dinic是从自己AC代码中快捷键出来的)
orz
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<iostream>
#define ll long long
#define N 10007
#define inf 214748364
using namespace std;
int read()
{
int ans=0;
char ch=getchar(),last=' ';
while(ch<'0'||ch>'9')last=ch,ch=getchar();
while(ch>='0'&&ch<='9')ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
return last=='-'?-ans:ans;
}
struct edg{
int next,to;
ll dis;
}edge[50*N];
int r,c,d,n,m,s,t,hea[N],num=1;
int dep[N],h[N],jz[22][22],zbx[N],zby[N],tot;
ll ans;
char getin[22];//输入用字符串数组
inline void add(int from,int to,ll dis)
{
num++;
edge[num].dis=dis;
edge[num].to=to;
edge[num].next=hea[from];
hea[from]=num;
}//链式存图
int getnumber(int a,int b,int judge)
{
if(!judge)
{
return (a-1)*c+b;//0代表入点
}
return (a-1)*c+b+r*c;//1代表出点
}//作用:通过横坐标(a),纵坐标(b)来确定对应的图中的点的编号是多少。
double diss(double x1,double y1,double x2,double y2)
{
return (y2-y1)*(y2-y1)+(x2-x1)*(x2-x1);
}
//计算长度函数
inline int bfs()//dinic
{
queue<int> q;
for(int i=1;i<=n;i++)
{
dep[i]=inf;
}
h[s]=hea[s];
q.push(s);
dep[s]=0;
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=hea[now];i;i=edge[i].next)
{
int v=edge[i].to;
if(dep[v]==inf&&edge[i].dis>0)
{
q.push(v);
dep[v]=dep[now]+1;
h[v]=hea[v];
if(v==t)return 1;
}
}
}
return 0;
}
ll dfs(int now,ll sum)//dinic
{
if(now==t)return sum;
ll nex=0,res=0;
for(int i=h[now];i&∑i=edge[i].next)
{
h[now]=i;
int v=edge[i].to;
if(edge[i].dis>0&&dep[v]==dep[now]+1)
{
nex=dfs(v,min(sum,edge[i].dis));
if(nex==0)dep[v]=inf;
edge[i].dis-=nex;
edge[i^1].dis+=nex;
res+=nex;
sum-=nex;
}
}
return res;
}
int main(){
r=read(),c=read(),d=read();//如题
s=0,t=r*c*2+1;//s是源点,t是超级汇点
for(int i=1;i<=r;i++)
{
cin>>getin;
for(int j=0;j<c;j++)
{
jz[i][j+1]=getin[j]-'0';//jz表示ij位置上的石柱高度
if(jz[i][j+1])
{
add(getnumber(i,j+1,0),getnumber(i,j+1,1),jz[i][j+1]);//入点向出点连长为石柱高度的边
add(getnumber(i,j+1,1),getnumber(i,j+1,0),0);//反向边
tot++;
zbx[tot]=i,zby[tot]=j+1;//记录有高度的石柱
}
}
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)//判断能否跳出去,如果能,向超级汇点连容量inf的边
{
if(jz[i][j])
{
if(i<d||i+d>r||j<d||j+d>c)
{
add(getnumber(i,j,1),t,inf);add(t,getnumber(i,j,1),0);
}
}
}
for(int i=1;i<=r;i++)//如果有蜥蜴,就从源点连容量为1的边
{
cin>>getin;
for(int j=0;j<c;j++)
{
if(getin[j]=='L')
{
add(0,getnumber(i,j+1,0),1);add(getnumber(i,j+1,0),0,0);
ans++;
}
}
}
for(int i=1;i<=tot;i++)//计算每一个有高度的石柱能跳到其他那些石柱
for(int j=1;j<=tot;j++)
{
if(i==j)continue;
if(diss(zbx[i],zby[i],zbx[j],zby[j])<=(double)d*d)
{
add(getnumber(zbx[i],zby[i],1),getnumber(zbx[j],zby[j],0),inf);
add(getnumber(zbx[j],zby[j],0),getnumber(zbx[i],zby[i],1),0);
}
}
while(bfs())//dinic
{
ans-=dfs(0,inf);
}
printf("%lld\n",ans);
return 0;
//TAT
}