题目地址:http://www.patest.cn/contests/pat-a-practise/1033
所用算法:贪心算法
分析:
1. 既然油箱初始为空,那么想要最便宜的方案,到终点的时候,油箱也必须为空。
2. 每个地点的加油策略:
设当前所在位置为 A,则开始寻找下一个加油位置,设为 B,将输入的加油站的位置按照距离的远近进行排序,每次遍历一个加油站。一次性跑的最远的距离为 maxPerTank = Cmax * Davg。
(1) 如果两个相邻的加油站之间的距离大于 maxPerTank,则无法到达终点,本次 case 结束。
(2) 若 B 点的油价低于 A 点,则需要油箱中的油量为可以恰好从 A 点跑到 B 点所需要的油量。
(3) 若 B 点的油价高于 A 点且两点之间的距离小于 maxPerTank,则查看下一个加油站。
(4) 若 B 点的油价高于 A 点但两点之间的距离大于 maxPerTank,则在 A 点加满油,并将 A 和 B 之间油价最便宜的加油站 C 为目的地,到达 C 以后,继续按照从 (2) - (4) 的步骤判断。
源代码(但在 PAT 中有一个测试用例无法通过,希望朋友们看出来代码的问题给我留言):
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
struct Station {
float P;
float Dis;
bool operator < (const Station &a) const {
return Dis < a.Dis;
}
};
short getMin(vector<Station> st, short begin, short end);
int main() {
cout.setf(ios::fixed);
short Cmax = 0, D = 0, Davg = 0, N = 0;
while (cin >> Cmax >> D >> Davg >> N) {
short maxPerTank = Cmax * Davg;
vector<Station> st(N);
// Accept Input
for (short i = 0; i < N; ++i) {
cin >> st[i].P >> st[i].Dis;
}
// 将目的地加入结点
Station des;
des.P = 0.0;
des.Dis = D;
st.push_back(des);
sort(st.begin(), st.end());
// 无法到达
float farthest = 0;
bool isReachable = true;
for (short i = 0; i < N; ++i) {
if (st[i].Dis + maxPerTank < st[i + 1].Dis) {
isReachable = false;
farthest = st[i].Dis + maxPerTank;
break;
}
}
if (!isReachable) {
cout << "The maximum travel distance = " << setprecision(2) << farthest << endl;
continue;
}
// 可以到达,计算最便宜的方案
float sum = 0.0;
float needGas = 0.0;
float nowPos = 0.0;
short i = 1, last = 0;
float priceLast = st[0].P;
float gasLeft = 0.0;
while (i < N + 1) {
if (st[i].Dis - nowPos <= maxPerTank) {
if (st[i].P < priceLast) {
needGas = (st[i].Dis - nowPos) / Davg;
if (gasLeft >= needGas) {
gasLeft -= needGas;
nowPos = st[i].Dis;
priceLast = st[i].P;
last = i;
++i;
} else {
sum += (needGas - gasLeft) * priceLast;
gasLeft = 0.0;
nowPos = st[i].Dis;
priceLast = st[i].P;
last = i;
++i;
}
} else {
++i;
}
} else {
short minPos = getMin(st, last + 1, i - 1);
sum += (Cmax - gasLeft) * priceLast;
gasLeft = Cmax - (st[minPos].Dis - nowPos) / Davg;
nowPos = st[minPos].Dis;
priceLast = st[minPos].P;
last = minPos;
i = minPos + 1;
}
}
cout << setprecision(2) << sum << endl;
}
return 0;
}
short getMin(vector<Station> st, short begin, short end) {
short ret = begin;
for (short i = begin; i <= end; ++i) {
if (st[i].P < st[ret].P) {
ret = i;
}
}
return ret;
}
希望朋友们多多指教!