正题
链接 需要纪中OJ账号
有n条木棒,长度为1或根号2,给出每根木棒两头的坐标,和燃烧需要的时间。只能从一个木棒的一头开始点火,求燃烧完所有木棒所需要的最短时间。
输入输出(需要自取)
Input
输入文件第一行为一个正整数N,表示组成图形的木棍数目,后面共有N行,每行5个数: X1 Y1 X2 Y2 T,其中(X1, Y1)和(X2, Y2)分别表示木棍两端的坐标,T表示木棍燃烧时间,是指从木棍的某一端点火燃烧到别一端,燃完所需的时间。
Output
输出文件是一个保留4位小数的实数,表示所有木棍完全燃烧的最少时间。
Sample Input
输入1:
1
0 0 1 1 1
输入2:
5
0 0 0 1 1
1 0 0 1 10
0 0 1 0 1
0 0 1 1 1
2 2 1 1 1
输入3:
3
1 1 1 2 10
1 2 2 2 10
1 1 2 2 50
Sample Output
输出1:
1.0000
解释:
从任一端点火都行,燃烧时间都是1
输出2:
3.2500
解释:
在 (0,0)位置点火木棍 1, 3 和 4 将被点燃,燃烧0.5分钟后,木棍2将被从中间点燃向两端燃烧,再过0.5分钟,木棍1, 3, 4 将被完全燃烧,木棍5 将被点燃并在1分钟后燃烧完 (比木棍2早燃完)。 木棍2从中间向两端燃烧0.5分钟以后,变成两小段,每段的燃烧时间是4.5 分钟。但因为此时两小段木棍的另一端也同时被点燃,燃烧速度变成原来的两倍,还需2.25 分钟的燃烧时间, 所以总时间: 1 + 2.25 = 3.25
输出3:
35.0000
解释:
在 (1,2)位置点火, 木棍(1 1, 1 2) 和(1 2, 2 2)将燃烧 10 分钟。. 最后一根木棍在10分钟后从两端被点燃,燃烧时间为25分钟。
解题思路
木棒可能在中间相连的情况只能在中间,所有加入一下中间点就好了。然后用Floyd最短路算出每个点到其他点的距离,不过所有的点烧完不代表木棒被烧完,所有我们需要枚举点开始烧的点,然后计算每个木棒需要燃烧的时间。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[1601][1601],n,x1,x2,x3,y1,y2,y3,m,wn;
bool mid[501];
double dis[501][501],mins,maxs,lon,ans,e[501][501];
int main()
{for (int i=0;i<=500;i++)for (int j=0;j<=500;j++){dis[i][j]=2147483647;e[i][j]=2147483647;}scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%d%d%d%d%lf",&x1,&y1,&x2,&y2,&lon);x1+=400;x2+=400;y1+=400;y2+=400;//转换为正数x1*=2;x2*=2;x3=(x1+x2)/2;y1*=2;y2*=2;y3=(y1+y2)/2;//求中间的坐标lon/=2;//分为两条木棍if (!a[x1][y1]){m++;//加入新坐标a[x1][y1]=m;//表示该坐标的点编号}if (!a[x2][y2]){m++;a[x2][y2]=m;}if (!a[x3][y3]){m++;a[x3][y3]=m;mid[m]=true;}dis[a[x1][y1]][a[x3][y3]]=lon;dis[a[x3][y3]][a[x1][y1]]=lon;dis[a[x2][y2]][a[x3][y3]]=lon;dis[a[x3][y3]][a[x2][y2]]=lon;//记录e[a[x1][y1]][a[x3][y3]]=lon;e[a[x3][y3]][a[x1][y1]]=lon;e[a[x2][y2]][a[x3][y3]]=lon;e[a[x3][y3]][a[x2][y2]]=lon;}for (int k=1;k<=m;k++)for (int i=1;i<=m;i++)for (int j=1;j<=m;j++){if (dis[i][k]<2147483647 && dis[k][j]<2147483647)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);//计算最短路}mins=2147483647;for (int k=1;k<=m;k++){if(mid[k]) continue; //排除在中间点ans=0;for (int i=1;i<=m;i++) ans=max(dis[k][i],ans);//取所有点烧完的所需时间for (int i=1;i<=m;i++)for (int j=i+1;j<=m;j++){if(e[i][j]<2147483647)if (dis[k][i]<e[i][j]+dis[k][j] && dis[k][j]<dis[k][i]+dis[i][j])//是否相接{ans=max(ans,max(dis[k][i],dis[k][j])+(e[i][j]-max(dis[k][i],dis[k][j])+min(dis[k][i],dis[k][j]))/2.0);//计算该木棒燃烧时间取最大值}}mins=min(ans,mins);//取最少的时间}printf("%.4lf",mins);
}