舒马赫的策略师
切了这个题,你也可以成为法拉利策略师
首先这个题的输入数据就比较多,好好整理一下再仔细思考这个题。
下面定义一下文中会出现的变量名的含义:
-
比赛的总圈数
int n -
理论上,没有油的空车跑一圈所需的时间
double emtt -
每增加
1 公升汽油,赛车跑一圈所增加的时间double inct -
理论上,没有油的空车跑一圈所消耗的油量
double emtg -
每增加
1 公升汽油,赛车跑一圈所增加的油量损耗double incg -
每次进站所需花费的时间
double pitt -
每次进站后,每加
1 公升汽油,所需花费的时间double pitg
(解释一下,其中的
在搞懂了题目之后不难发现这玩意是动态规划,暂定 维斯塔潘舒马赫跑了
首先,如果只跑一圈,我们可以列出来这样一个关于耗油量
然后同理可得,对于跑
由此得到递推式
然后由于我们每次跑
接下来就是正经的 dp 部分,stack 按顺序输出。
时间复杂度
贴代码!(目前 30ms,最快哦)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
typedef long long lol;
typedef pair<int, int> pii;
typedef unsigned int uin;
const int N = 505;
int n;
double emtt, inct, emtg, incg, pitt, pitg;
double gas[N], lap[N], f[N];
int pre[N];
int main () {
scanf ("%d%lf%lf%lf%lf%lf%lf", &n, &emtt, &inct, &emtg, &incg, &pitt, &pitg);
for (int i(1); i <= n; ++ i )
gas[i] = (gas[i - 1] + emtg) / (1 - incg),
lap[i] = lap[i - 1] + emtt + gas[i] * inct,
f[i] = 1e18;
for (int i (1); i <= n; ++ i )
for (int j (0); j < i; ++ j )
if (j)
{
double t = f[j] + pitt + gas[i - j] * pitg + lap[i - j];
if (f[i] > t)
f[i] = t, pre[i] = j;
}
else
{
double t = f[j] + lap[i - j];
if (f[i] > t)
f[i] = t, pre[i] = j;
}
stack <pii> s;
int u = n;
while (pre[u])
s.push(pii (pre[u], u - pre[u])),
u = pre[u];
printf ("%.3lf %.3lf %d\n", f[n], gas[u], s.size());
while (!s.empty())
printf ("%d %.3lf\n", s.top().first, gas[s.top().second]), s.pop();
return 0;
}