題目鏈接:傳送門
思路:本來想dp,然後得了11分,因爲沒有考慮在前一個加油站可以加滿油的情況。 下來說貪心解法:首先每個位置取最小的油價保存,然後在計算時分兩種情況,設當前位置爲t。
(1)前方有價格更低的加油站p,直接選取這個加油站p,然後記錄走到這個加油站要花費的錢.
(2)前方沒有價格更低的加油站,爲了到達需要選取一個價格相對最小的站p1,這裏可以先在當前加油站t加滿油,再去目標加油站p1,所以算的時候直接算上加滿油的油錢,然後記錄一個免費距離ol,在下一個加油站p1可以用。(在下一個加油站p1計算時的時候直接減掉這段距離即可,不會減成負的 , 可以證明)
代碼:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e4 + 5 , INF = 0x7f7f7f7f;
double g[maxn];
vector <int> v;
int main() {
int c , d , da , n;
cin >> c >> d >> da >> n;
for(int i = 0 ; i <= d ; i++)g[i] = INF;
for(int i = 0 ; i < n ; i++) {
double p;
int dst;
cin >> p >> dst;
if(g[dst] == INF)v.push_back(dst);
if(g[dst] > p)g[dst] = p;
}
g[d] = 0; v.push_back(d);
sort(v.begin() , v.end());
int cnt = 0;
double ans = 0;
double ol = 0;
if(v[0] > 0) {
printf("The maximum travel distance = 0.00\n");
return 0;
}
//cout << "size = " << v.size() << "\n";
for(int i = 0 ; i < v.size() - 1 ; ) {
int t = i;
int x = -1;
i++;
double mm = INF;
while(i < v.size() && v[i] - v[t] <= c * da) {
if(g[v[i]] < mm) {
x = i;
mm = g[v[i]];
if(mm < g[v[t]])break;
}
i++;
}
if(x != -1) {
if(mm > g[v[t]]) {
ans += (double)(c - ol / da) * g[v[t]];
ol = c * da - (v[x] - v[t]);
}
else {
ans += (double)(v[x] - v[t] - ol) / da * g[v[t]];
ol = 0;
}
cnt = v[x];
i = x;
}
else {
cnt = v[t] + c * da;
printf("The maximum travel distance = %.2f\n" , (double)cnt);
return 0;
}
}
printf("%.2f\n" , ans);
return 0;
}