PAT (Advanced Level) 1033 To Fill or Not to Fill (25分)【贪心】
题意:给你油箱容量
C
C
C,给你最远想要到达的距离
D
D
D,给你汽车每升油所能支持的距离
D
a
v
g
D_{avg}
Davg,给你加油站的数量
N
N
N。
然后每个加油站,给你距离起点的位置以及油价。
问,你最少可以花费多少美元到达终点。
分析:作为老 D P DP DP 恐慌性选手,起手就是一顿动态规划,然而最后复杂度在 30000 ∗ 500 ∗ 500 30000 * 500* 500 30000∗500∗500 最后一个测试点最直接 T L E TLE TLE.
本题可通过贪心的思想来实现,我需要维护当前油箱里的剩余油量。
-
假设我已经抵达一个加油站,如果我的装满油箱足以支撑我到达下一个油价更便宜的加油站:
1 要么我油箱里的油足够,我就选择不在当前加油站加油;跳到离我当前位置最近的油价比当前加油站油价低的加油站
2 要么我油箱里的油不够,我就恰好加到可以抵达下一个拥有更便宜油价的加油站。跳到目的加油站 -
假设我抵达了一个加油站,在当前加油站到我装满油箱所能到达的距离的区间之内,没有更便宜的加油站:
1 我加满油可以抵达终点,直接加油加到恰好可以抵达终点,跳到终点
2 加满油并不能抵达终点,直接把油加满,然后跳到剩下区间内油价最便宜的那个加油站
WA点:
- 注意,你选取的下一个加油站不是下一个区间里油价最低的,而是离你最近的油价比你低的。建议先手算一遍第一个样例。
- 注意,如果起点没有加油站,最远距离直接输出为 0.00 0.00 0.00
- 使用 d o u b l e double double
贪心AC代码:
#include<iostream>
#include<cstring> //memset
#include<string>
#include<cstdio> //scanf
#include<string>
#include<utility> // pair
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<functional> //less greater
using namespace std;
//MSMYS
// the same node may be at different position(address).
#define LL long long int
#define ll LL
#define INF 0x3f3f3f3f
const double eps = 1e-8;
const double TINF = 1e10;
const int maxn = 5e2 + 10;
const int maxm = 3e4 + 10;
double dp[maxm];
double money[maxm];
struct Gas_Station {
int id;
int pos;
double price;
}a[maxn];
int C, D, Davi, N;
int cmp(Gas_Station A, Gas_Station B) {
if (A.pos == B.pos) return A.price < B.price;
return A.pos < B.pos;
}
int main() {
scanf("%d %d %d %d", &C, &D, &Davi, &N);
for (int i = 0; i < maxm; i++) {
money[i] = TINF;//没有加油站
}
for (int i = 1; i <= N; i++) {
double pri; int distance;
scanf("%lf %d", &pri, &distance);
a[i].price = pri;
a[i].pos = distance;
money[distance] = min(pri, money[distance]);
}
money[D] = 0;
int MaxDAC = C * Davi;
sort(a + 1, a + 1 + N, cmp);
double res = 0.0; // the capacity of gas tank
double cost = 0.0; // the cost of gas nw
//double length = 0; // the length of the gas in tank can be successive.
int dis = 0;
if (a[1].pos > 0) {
puts("The maximum travel distance = 0.00");
return 0;
}
int k = 0;
//多出来三公里的钱!
while (dis <= D) {
double Price = money[dis];
double length = res * Davi; // 当前油箱内剩余油所可以支持的距离
double MinPrice = TINF - 10; int index = -1; int flag = 0;
for (int i = dis + 1; i <= dis + MaxDAC && i <= D; i++) {
if (money[i] < MinPrice && i != D) {
flag = 1;
index = i;
MinPrice = money[i];
}
if (MinPrice <= Price) {
break;
}
if (i == D) {
if (!flag) {
index = D;
MinPrice = 0;
}
}
}
if (index != -1 && MinPrice <= Price) {
if (dis + length >= index) { // 直接跑过去,当前加油站不用加油
res = res - (index - dis) / Davi;
dis = index;
}
else { // 刚刚好加油加到下一个加油站
cost += 1.0 * (index - dis - length) / Davi * Price;
res = 0;
dis = index;
}
}
else {
if (index == -1) {
if (dis + MaxDAC <= D) {
dis = dis + MaxDAC;
cost += 1.0*(C - res) * Price;
res = 0;
}
else {
cost += 1.0*(D - dis - length) / Davi * Price;
res = 0;
dis = D;
}
break;
}
else {
if (dis + MaxDAC >= D) {
cost += 1.0*(D - dis - length) / Davi * Price;
res = 0;
dis = D;
}
else {
cost += 1.0*(C - res)*Price;
res = C - 1.0*(index - dis) / Davi;
dis = index;
}
}
}
//printf("%.2f\n", cost);
}
if(dis == D)
printf("%.2f\n", cost);
else printf("The maximum travel distance = %.2f\n", 1.0 * dis);
return 0;
}
DP TLE 代码:回来再琢磨琢磨能不能优化
#include<iostream>
#include<cstring> //memset
#include<string>
#include<cstdio> //scanf
#include<string>
#include<utility> // pair
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<functional> //less greater
using namespace std;
//MSMYS
// the same node may be at different position(address).
#define LL long long int
#define ll LL
#define INF 0x3f3f3f3f
const double eps = 1e-8;
const double TINF = 1e10;
const int maxn = 5e2 + 10;
const int maxm = 3e4 + 10;
double dp[maxm];
struct Gas_Station {
int id;
int pos;
double price;
}a[maxn];
int C, D, Davi, N;
int cmp(Gas_Station A, Gas_Station B) {
if (A.pos == B.pos) return A.price < B.price;
return A.pos < B.pos;
}
int main() {
scanf("%d %d %d %d", &C, &D, &Davi, &N);
for (int i = 1; i <= N; i++) {
double pri; int distance;
scanf("%lf %d", &pri, &distance);
a[i].price = pri;
a[i].pos = distance;
}
for (int i = 0; i <= D; i++) {
dp[i] = TINF;
}
dp[0] = 0.0;
int MaxDAC = C * Davi;
//cout << MaxDAC << endl;
sort(a + 1, a + 1 + N, cmp);
int pre_distince = 0;
for (int i = 1; i <= N; i++) {
int Pos = a[i].pos;
//只考虑这个加油站可能影响的距离
for (int j = Pos; j <= Pos + MaxDAC; j++) {
for (int k = Pos; k <= j; k++) {
double tmp = dp[k] + 1.0 * (j - k) / Davi * a[i].price;
dp[j] = min(tmp, dp[j]);
}
}
}
if (dp[D] > TINF - 10.0) {
for (int i = 0; i <= D; i++) {
if (dp[i + 1] > TINF - 10.0) {
printf("The maximum travel distance = %.2f\n", 1.0*i);
return 0;
}
}
}
printf("%.2f\n", dp[D]);
/*for (int i = 1; i <= 10; i++) {
printf("%.2f\n", dp[i]);
}
*/
return 0;
}