目录:
题目:
题意:
给出我们一个木棍图,求将其全部燃烧完至少要多久时间。
分析:
这道题目,难度肯定是有的,所以这就需要我们理清思路,且要非常明了,下面请让小编带你走进思维的殿堂。
首先我们可以想到的就是最短路,而在这题中,使用
Floyd
算法会比
Dij
方便很多,且不需我们去做任何多余的处理,所以在这点上小编就不多讲了。
其次,也是难点,就是我们要如何去计算他们全燃烧完的时间。
求出从某个点到其它点的最短时间以后,余下的问题是检查每一边是否完全燃烧。如果没有完全燃烧,求出剩余边燃烧所需最长时间。
对于燃烧时间为L的木棍,它的两端被点燃的时刻为T1和T2,如果T1 = T2+L 或者是 T2 = T1+L,那么燃烧到T1 和 T2 的最大时刻,这根木棍己经完全燃烧。
如果T1与T2之间的时间差不等于L,那么就说明火是从不同的路径燃烧到这根木棍的两端。火将从两端向中间燃烧,并在木棍内的某个点燃完,在简单情况中,如果是从两端同时点燃,燃烧时间为L/2。更一般地,如果T1与T2不等,我们设一端是从0时刻点燃,另一端是从T时刻点燃,那么这根木棍的燃烧时间为T+(L-T)/2。
AC后感想:
在做的过程中,几度想哭,但在抠标经过讲解后,再冷静下来,重新打了一遍后,就AC了。只能说此题考查选手用图解决问题的能力,并且此题不能简单的套用
Floyed
算法,需要选手在解决问题中灵活运用经典算法。
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#define r(i,a,b) for(int i=a;i<=b;i++)
#define LL long long
using namespace std;
inline LL read()
{
LL a=0,f=1;char s=getchar();
while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
while(s>='0'&&s<='9') {a=a*10+s-'0';s=getchar();}
return a*f;
}
int n,m;
double ans=99999999,cc;
double fmax(double x,double y){return x>y?x:y;}
double fmin(double x,double y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
struct node1
{
int x1,y1,x2,y2,t;
}f[45];//读入数组
struct node2
{
int x,y;
}v[101];//边
int w[101][101],dis[101][101];//燃烧时间以及最短路
int find(int x,int y)
{
r(i,1,m)//判断之前是否有出现过
if(v[i].x==x&&v[i].y==y)
return i;
m++;//边数+1
v[m].x=x;
v[m].y=y;
r(i,1,m-1)//初始化w
w[i][m]=w[m][i]=99999999;
w[m][m]=0;
return m;
}
void gt(int x1,int y1,int x2,int y2,int t)//构图
{
int x=find(x1,y1);
int y=find(x2,y2);
w[x][y]=w[y][x]=t;
}
void fz()//将w复制给dis
{
r(i,0,100)
r(j,0,100)
dis[i][j]=w[i][j];
}
void floyed()//最短路
{
r(k,1,m)
r(i,1,m)if(dis[i][k]<99999999)
r(j,1,m)if(dis[k][j]<99999999)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
double fire(int k)//燃烧——重头戏!!!
{
double now=0,s=0;
r(i,1,m)
if(dis[k][i]>now) now=dis[k][i];//求最慢的
r(i,1,m-1)
r(j,i+1,m)
if(w[i][j]<99999999)//如果有连通
if(dis[k][i]<dis[k][j]+w[i][j]&&dis[k][j]<dis[k][i]+w[i][j])
//如果两端都会燃烧
if(dis[k][i]<dis[k][j])//求最慢的,用公式
now=fmax(now,dis[k][j]+(w[i][j]-(dis[k][j]-dis[k][i]))/2.0);
else
now=fmax(now,dis[k][i]+(w[i][j]-(dis[k][i]-dis[k][j]))/2.0);
return now;
}
int main()
{
n=read();
r(i,1,n)
f[i].x1=read(),f[i].y1=read(),f[i].x2=read(),f[i].y2=read(),f[i].t=read();
r(i,1,n)
{
//*2和+,都是为了保证点的唯一性
gt(f[i].x1*2,f[i].y1*2,f[i].x1+f[i].x2,f[i].y1+f[i].y2,f[i].t);
gt(f[i].x1+f[i].x2,f[i].y1+f[i].y2,f[i].x2*2,f[i].y2*2,f[i].t);
}
fz();
floyed();
r(i,1,m)
if(!(v[i].x&1)&&!(v[i].y&1))//时间优化:只看其中一点
//ps:我们之前在gt*2了,所以肯定是偶数
ans=fmin(ans,fire(i));
printf("%0.4lf",ans/2);//我们在算点时*2,所以输出时就/2
}