题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6581
题目大意:单行道上在tom的车前面有 n辆车,每辆车有一个速度和车长,以及它们车头到终点的距离,因为有的车快有的车慢,最终车会挨在一起,如果两车挨在一起,那么后面的车速度会慢下来跟前面的车一样快,多辆车挨在一起也是同理。问tom的车的车头过终点线的时间是多少。
分析:由于多辆车合并在一起,后面的车的速度会受影响,但车头是不受影响的,车头仍然按自己的速度在跑。最后tom的车一定是接在某辆车的后面越过终点(也可以没接在某辆车后面,这种情况可以当成接在自己后面)。车头不受影响,可以枚举车头是哪个,然后计算tom的车过终点的时间,取最大值。因为最后一定是跟着某辆车通过终点,如果你枚举的车头实际上在tom过终点之前都不能和这辆车合并,那么算出来的tom过终点的时间一定是缩短了,因此取最大值得出的是正解而且不会遗漏解。
#include<iostream>
using namespace std;
#include<stdio.h>
#include<string.h>
#include<queue>
int t,n;
const int maxn = 1e5 + 10;
double s[maxn],l[maxn],v[maxn];
int p[maxn],d[maxn],num[maxn];
int main() {
while(~scanf("%d",&n)) {
for(int i = 0; i <= n; i++)
scanf("%lf",&l[i]);
for(int i = 0; i <= n; i++)
scanf("%lf",&s[i]);
for(int i = 0; i <= n; i++)
scanf("%lf",&v[i]);
double ans = 0,tmp = l[0];
for(int i = 0; i <= n; i++) {
if(i)
l[i] += l[i - 1];
ans = max(ans,(s[i] + l[i] - tmp) / v[i]);
}
printf("%.11lf\n",ans);
}
return 0;
}
由于答案具有单调性:时间越长,tom越可能越过终点,可以二分时间,然后从后往前计算每辆车的所在的位置,判断一下tom的车的位置是否越过了终点。
#include<iostream>
using namespace std;
#include<stdio.h>
#include<string.h>
#include<queue>
int t,n;
const int maxn = 1e5 + 10;
const double eps = 1e-11;
double s[maxn],l[maxn],v[maxn];
int p[maxn],d[maxn],num[maxn];
double find() {
double li = 0,ri = 1e9 + 1;
while(ri - li > eps) {
double mid = (li + ri) / 2;
double lastpos;
for(int i = n; i >= 0; i--) {
if(i == n || s[i] - v[i] * mid > lastpos + l[i + 1])
lastpos = s[i] - v[i] * mid;
else lastpos += l[i + 1];
}
if(lastpos <= 0)
ri = mid;
else li = mid + eps;
}
return li;
}
int main() {
while(~scanf("%d",&n)) {
for(int i = 0; i <= n; i++)
scanf("%lf",&l[i]);
for(int i = 0; i <= n; i++)
scanf("%lf",&s[i]);
for(int i = 0; i <= n; i++)
scanf("%lf",&v[i]);
double ans = find();
printf("%.11lf\n",ans);
}
return 0;
}