贪心策略Java版
1.添加终点加油站(路程,0)。0表示价格为0。
2.先将所有加油站按照距离远近排序,距离相同则按照价格从低到高排序。
3.从index = 1开始寻找比当前加油站(index = 0)处价格低的最近加油站(这些加油站必须在油箱加满后能开车到达的距离内),找到一个最近的,则将油加到正好开车到价格低的加油站所需油量。计算花费,车开到加油站油量耗尽。更新index、当前距离currentDist、当前加油站价格currentCost。
4.如果在index = 1处,在能到达的范围内没有比当前价格更低的加油站,那改变策略:寻找能到达的所有加油站中价格最低但是比当前价格高的加油站,接着在当前加油站加满油,开车过去。此时剩余油量remain为capacity-路程所需油量。计算花费,更新index、currentDist、currentCost。
5.重复步骤3-4,直到布尔变量way==false,加满油也无法到达下一加油站。或者currentDist==dist(终点)。退出循环。
6.布尔变量less代表是否找到步骤3中描述的价格较低的加油站。
7.compare方法的重写:返回-1表示后面的值(o2)与前面的值(o1)需要互换位置。返回0和1则不用。
这个思路我觉得是比较好的,易于理解,我理解了思路后用Java重写的算法。参考的文章是用C++写的,大家都用C++,看来我以后也得学C++了。
参考思路链接:https://blog.csdn.net/RPG_Zero/article/details/100598669
import java.util.*;
public class Main {
public static void main(String[] args) {
go();
}
// 15 2383 13 10
// 424238335 0
// 86 60
// 49 161
// 62 1033
// 90 1279
// 63 1891
// 40 311
// 72 13
// 11 1945
// 67 1095
public static void go() {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int capacity = in.nextInt();
int dist = in.nextInt();
int efit = in.nextInt();
int n = in.nextInt();
ArrayList list = new ArrayList();
for (int i = 0; i < n; i++) {
list.add(new Station(in.nextDouble(), in.nextInt()));
}
list.add(new Station(0, dist));
// 加油站排序
Collections.sort(list, new Comparator() {
public int compare(Station o1, Station o2) {
if (o1.dist < o2.dist) {
return -1;
}else if (o1.dist > o2.dist){
return 1;
}else {
if (o1.price < o2.price) {
return -1;
}else {
return 1;
}
}
}
});
// 如果排序后第一个加油站都无法到达,此处我直接return了,但是按理来讲应该设置next为true然后break进行下一个用例计算。
if (list.get(0).dist != 0) {
return;
}
double totalCost = 0;
int currentDist = 0;
double currentCost = list.get(0).price;
int index = 1;
int max = capacity * efit;
double remain = 0;
boolean next = false;
// 外层循环记录每一次判断汽车是否能够开往下一个加油站
while (currentDist < dist) {
boolean way = false;
boolean less = false;
// 第一个for循环寻找是否有比当前价格便宜的最近加油站
for (int i = index; i <= n; i++) {
Station temp = list.get(i);
if (max + currentDist >= temp.dist) {
way = true;
if (currentCost >= temp.price) {
less = true;
index = i;
break;
}
}else {
break;
}
}
// 不能到达下一个加油站,输出最大行驶距离,进行下一个用例
if (!way) {
System.out.printf("The maximum travel distance = %.2f", currentDist + (capacity - remain) * efit);
System.out.println();
next = true;
break;
}
// 找到了价格更低的加油站,加刚好满足距离要求的***驶过去。
if (less) {
Station s = list.get(index);
int len = s.dist - currentDist;
double need = (double)len / efit;
if (need >= remain) {
totalCost += (need - remain) * currentCost;
remain = 0;
}else {
remain -= need;
}
currentDist = s.dist;
currentCost = s.price;
index++;
}else {// 没找到价格更低的加油站,找价格高一些的最便宜加油站,行驶过去。
double minCost = Double.MAX_VALUE;
for (int j = index; j <= n; j++) {
Station temp = list.get(j);
if (max + currentDist >= temp.dist) {
if (minCost > temp.price) {
index = j;
minCost = temp.price;
}
}else {
break;
}
}
Station s = list.get(index);
int len = s.dist - currentDist;
double need = (double)len / efit;
totalCost += (capacity - remain) * currentCost;
remain = capacity - need;
currentDist = s.dist;
currentCost = s.price;
index++;
}
}
// 到达不了重点,进行下一个用例
if (next) {
continue;
}
// 到达重点,输出总花费
System.out.printf("%.2f", totalCost);
}
}
}
class Station{
public double price;
public int dist;
public Station(double price, int dist) {
super();
this.price = price;
this.dist = dist;
}
}


京公网安备 11010502036488号