CF5D Follow Traffic Rules
[难度 2100]
题目内容(洛谷链接, CF链接)
两个城市之间有一条直达路,路上只放了一个限速牌。限速牌只限制它所在那一点的速度,驶过限速牌可以以任意速度行驶。
市民们的汽车加(减)速度恒为 \(a\ \mathrm{km/h^2}\),且最大速度为 \(v\ \mathrm{km/h}\)。路总长为 \(l\ \mathrm{km}\)。限速牌限速为 \(w\ \mathrm{km/h}\),被放在距离起点城市 \(d\ \mathrm{km}\) 的位置上。汽车在起点速度为 \(0\)。要求找到市民们在最优情况下,通过该路的最短时间。
汽车可以以任意速度进入终点城市。
题意
在公路上以 最短时间 为目的行驶汽车,公路上存在着一个限速牌(经过的时候,瞬时速度不能超过限制速度)
是非常经典的物理题目
- 由常识可以知道,全程保持加速是耗时最短的
- 而针对限速牌,可以先加速至\(v_p\),再减速至经过限速牌时,刚好满足\(v=w\)
已知物理公式如下:
\(v2 - v_0 2 = 2 * a * x\)
\(\Delta v = v - v_0 = a * t\)
则可以定义几个 函数
\(speedUpUntilV(\_v) : x\) 将 \(v_0\) 加(减)速至 \(\_v\) 并返回经过的位移 \(x\)
\(reachX_v(\_x) : v\) 一直加速,返回 位移 \(\Delta x\) 达到 \(\_x\) 时的瞬时速度 \(v\)
\(speedUpUntilX(\_x) : t\) 一直加速(若达到 \(vMax\) 则变为匀速),返回 位移 \(\Delta x\) 达到 \(\_x\) 时的所经过的时间 \(t\)
定义完 函数 后即可解出该题
AC代码
Info: [360ms / 8.00KB / 1.30KB / C++11]
点击查看代码
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
double a, vMax, l, d, w, v0 = 0.0, ans = 0.0;
void fread(double &p)
{
int t = 0; char ch = getchar();
while (ch < '0' || '9' < ch)
ch = getchar();
while ('0' <= ch && ch <= '9')
t = (t << 1) + (t << 3) + ch - '0', ch = getchar();
p = (double)t;
}
double speedUpUntilV(double _v)
{
if (_v < v0)
_v += v0, v0 = _v - v0, _v -= v0;
_v = min(_v, vMax);
double delta_t = (_v - v0) / a;
double x = ((_v * _v) - (v0 * v0)) / (2.0 * a);
ans += delta_t;
v0 = _v;
return x;
}
double reachX_v(double _x)
{
return sqrt(2 * a * _x + v0 * v0);
}
double speedUpUntilX(double _x)
{
double oTime = ans;
_x -= speedUpUntilV(reachX_v(_x));
if (_x > 0.0)
{
ans += (_x / v0);
}
return ans - oTime;
}
int main()
{
#ifdef WatPz
freopen("FTR.in", "r", stdin);
freopen("FTR.out", "w", stdout);
#endif
fread(a), fread(vMax), fread(l), fread(d), fread(w);
if (min(reachX_v(d), vMax) <= w)
{
speedUpUntilX(l);
}
else
{
ans += speedUpUntilX((d - speedUpUntilV(w)) / 2);
v0 = w;
speedUpUntilX(l - d);
}
printf("%.12f", ans);
#ifdef WatPz
fclose(stdin);
fclose(stdout);
#endif
return 0;
}

浙公网安备 33010602011771号