#include <bits/stdc++.h>
using namespace std;
double di[101], pi[101], d, c, d0;
int n;
// 寻找下一个加油站
int find_min(int start)
{
if(start == n) return n+1;
double dend = di[start] + c*d0;
int k = n;
while(di[k]-di[start] > dend) k--;
if(k == start) // 开不到下一个加油站
return -2;
for(int i = k-1; i >= start+1; i--)
{
if(pi[i] < pi[k])
k = i;
}
if(pi[k] > pi[start]) // 后面没有更便宜的加油站
{
if(dend >= di[n+1]) // 能开到终点
return n+1;
return -1; // 开不到终点
}
return k;
}
int main()
{
cin >> d >> c >> d0 >> pi[0] >> n;
if(n == 0) // 中间没有加油站
{
if(c*d0 >= d)
printf("%.2lf", d/d0*pi[0]);
else
printf("No Solution");
return 0;
}
for(int i = 1; i<= n; i++)
{
cin >> di[i] >> pi[i];
}
di[n+1] = d;
int cur = 0, next;
double rest = 0, cost = 0;
while(1)
{
next = find_min(cur); // 找到从当前加油站能开到的最远的加油站
//printf("now:%d, next:%d, rest:%.2lf, dist:%.2lf\n", cur, next,rest,rest*d0);
if(next == n+1) // 如果能开到终点
{
if(rest*d0 < di[n+1]-di[cur])
{
//printf("加%.2lf钱\n",(di[n+1]-di[cur]-rest*d0)/d0*pi[cur]);
cost += (di[n+1]-di[cur]-rest*d0)/d0*pi[cur];
}
// else
// printf("不用加油\n");
// 加能开到终点的油
printf("%.2lf", cost);
return 0;
}
else if(next == -1) // 开不到终点,且没比当前更便宜的加油站
{
// 加满油,开到下一个加油站
//printf("加满, 加%.2lf钱\n", (c-rest)*pi[cur]);
cost += (c-rest)*pi[cur];
rest = c - (di[cur+1]-di[cur])/d0;
cur++;
}
else if(next == -2)
{
printf("No Solution");
return 0;
}
else // 有更便宜的加油站,开到该加油站
{
if(rest*d0 < di[next]-di[cur])
{
//printf("该加油站便宜,加%.2lf钱\n", (di[next]-di[cur]-rest*d0)/d0*pi[cur]);
// 只加刚好够行使到该加油站的油量
cost += (di[next]-di[cur]-rest*d0)/d0*pi[cur];
rest = 0;
}
else
{
//printf("不加油,够用\n");
rest -= (di[next]-di[cur])/d0;
}
cur = next;
}
}
return 0;
}
TOPS [NOIP1999 提高组] 旅行家的预算
最新推荐文章于 2024-10-14 09:08:48 发布