1004 Vacation
说是大模拟,其实应该还是算一个思维题,想到了就可以比较简单的写出来,不然就是像我一样写两个半小时出来疯狂wa,还是太菜了QAQ
第一种解法:
二分时间,感觉这种解法对这类题目应该都可以,只要数据稍微友好一点,不要精度不够,double因该是不会爆掉的,他的数据范围很大
bool ch()函数是最重要的,就是他判断当前时间是否是合法的,从最靠近终点线的方法去推断,每一辆车行驶当前时间是否会超,如果超了,那么就是只行驶到前面一个的位置(这里做一个说明,这个思想在下一种解法中也会有,就是追及的距离,两者时间是一样的,而后面则是按照慢的挡在前面的那一个的速度行驶的,其实和慢的那个行驶的时间是一样的,因为前后两个阶段的时间是一样的。QAQ不知到讲清楚了没有,如果没有的话,读者自己稍微感受一下这个想法 )
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=1e5+100;
const double maxt=1e9+100;
double l[MAXN],s[MAXN],v[MAXN];
double f[MAXN];
int n;
/*
判断一个时间是否合法 从离终点线最近的点往前推 算一下每辆车在时间mt时的位置
最右边的车可以一直最高速度走
其他车如果走的比他前面的车远 等于他前面的车的位置
反之等于自己的最远位置
*/
bool ch(double mt)
{
for(int i=n;i>=0;i--){
f[i]=s[i]-v[i]*mt;
if(i==n) continue;
else f[i]=max(f[i],f[i+1]+l[i+1]);
}
return f[0]<=0;
}
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 l=0,r=maxt;
while(l<r&&(r-l)>(1e-10)){
double mt=(l+r)/2;
if(ch(mt))//说明时间太长了
r=mt;
else//说明时间太短了
l=mt;
}
printf("%.10f\n",l);
}
return 0;
}
第二种解法:
0车可能会自己驶过终点线,也有可能被别的车堵着驶过终点线,所以对于每一辆车,假设是它是和0车堵在一起的最靠前的一辆车,那么可以计算出一个值,所有的车的计算值的最大值就是答案。对于被一个车堵着驶过终点线,的时间,就是最后一辆车用那辆堵着的车的速度行驶前面所有的车长和最前面那一辆车的距离(这个思想就是上面说的那一个,再讲一遍,希望能讲清楚把。 就是0车按照非堵着的车速度行驶的距离就是,前面的车全部撞在一起的时间,就是追及时间,那么就等于这段时间内堵着的车行驶的时间,后面就是大家一起行驶了,那么就是还是等于堵着的车的行驶的时间,而且还要多形式一段车长的总和)
# include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+100;
int l[MAXN];
int s[MAXN];
int v[MAXN];
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<=n;i++) scanf("%d",&l[i]);
for(int i=0;i<=n;i++) scanf("%d",&s[i]);
for(int i=0;i<=n;i++) scanf("%d",&v[i]);
double ans=0.0;
double sum=0.0;
ans=s[0]*1.0/v[0]*1.0;
for(int i=1;i<=n;i++){
sum+=l[i]*1.0;
ans=max(ans,(sum+s[i]*1.0)/v[i]*1.0);
}
printf("%.10f\n",ans);
}
return 0;
}