Description
Solution
根据木棍的长度只有 \(1\) 和 \(\sqrt{2}\) 可知,若两根木棍相交,则一定交在中点。
那我们先将所有点的坐标变成两倍,时间也变成两倍,然后对于长度为 \(\sqrt{2}\) 的木棍,取中点,向两个端点连长度为 \(t\)(因为是\(\frac{2t}{2}\)) 的边。长度为 \(1\) 的木棍就直接将两个端点连起来,长度为 \(2t\)。
然后跑 \(\mathrm{Floyd}\)。枚举每个点作为起点(注意不要枚举新增的中点),求出其到最远的点的燃烧时间。但在这个时间内可能有些边没烧完。所以再遍历所有边,找出需要额外时间最多的边,加入答案。
最后将答案除以 2,因为之前将时间变成了两倍。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 50
#define X 805
#define db double
using namespace std;
struct node
{
int t,x1,y1,x2,y2,typ;
}edg[N];
struct edge
{
int x,y,v;
}a[N<<2];
int n,x1,x2,y1,y2,t,cnt,tot,sum1,sum2,id[X][X],dis[N<<2][N<<2];
db ans;
bool bj[N][N];
void add(int x,int y,int z)
{
a[++tot].x=x;
a[tot].y=y;
a[tot].v=z;
dis[x][y]=z;
}
int main()
{
freopen("fire.in","r",stdin);
freopen("fire.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i)
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&t);
x1*=2;y1*=2;x2*=2;y2*=2;t*=2;
x1+=400;x2+=400;y1+=400;y2+=400;
if (!id[x1][y1]) id[x1][y1]=++cnt;
if (!id[x2][y2]) id[x2][y2]=++cnt;
edg[i].t=t;
edg[i].x1=x1;edg[i].y1=y1;edg[i].x2=x2;edg[i].y2=y2;
if (x1==x2||y1==y2) edg[i].typ=1;
else edg[i].typ=2;
bj[id[x1][y1]][id[x2][y2]]=bj[id[x2][y2]][id[x1][y1]]=true;
}
memset(dis,0x3f3f3f3f,sizeof(dis));
for (int i=1;i<=n;++i)
{
x1=edg[i].x1;y1=edg[i].y1;
x2=edg[i].x2;y2=edg[i].y2;
t=edg[i].t;
if (edg[i].typ==1) add(id[x1][y1],id[x2][y2],t),add(id[x2][y2],id[x1][y1],t);
else
{
if (x1>x2) swap(x1,x2),swap(y1,y2);
if (id[x1][y2]&&id[x2][y1]&&bj[id[x1][y2]][id[x2][y1]])
{
int x=(x1+x2)/2,y=(y1+y2)/2;
if (!id[x][y]) id[x][y]=++cnt;
add(id[x1][y1],id[x][y],t/2);
add(id[x][y],id[x1][y1],t/2);
add(id[x][y],id[x2][y2],t/2);
add(id[x2][y2],id[x][y],t/2);
}
else
{
add(id[x1][y1],id[x2][y2],t);
add(id[x2][y2],id[x1][y1],t);
}
}
}
for (int i=1;i<=cnt;++i)
dis[i][i]=0;
for (int k=1;k<=cnt;++k)
for (int i=1;i<=cnt;++i)
for (int j=1;j<=cnt;++j)
if (i!=j&&i!=k&&j!=k)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
ans=2147483647.0;
for (int i=1;i<=n;++i)
{
sum1=sum2=0;
for (int j=1;j<=cnt;++j)
sum1=max(sum1,dis[i][j]);
for (int j=1;j<=tot;++j)
{
int x=a[j].x,y=a[j].y,v=a[j].v;
int c=sum1-dis[i][x]+sum1-dis[i][y];
if (c>=v) continue;
sum2=max(sum2,v-c);
}
ans=min(ans,(db)((sum1+sum2/2.0)/2.0));
}
printf("%.4lf\n",ans);
return 0;
}