生命不息,奋斗不止!
@author stormma
@date 2017/10/20
题意:一辆卡车距离城镇L单位长度,初始有P油,每行驶一个单位长度消耗一单位油。有n个加油站可以加油,给出n个加油站与城镇的距离Ai,和在加油站可以加的有的量Bi,问最少加油几次才能行驶L长度,如果不能输出-1。
我们稍微变换一下思路:每次经过加油站,都把油装到瓶子里面带走,Bi加入优先队列,到需要加油的时候才加,因为需要使加油的次数最少,每次都是选油量最大的加。如果优先队列为空而没有到达下一加油站或是终点。则不能够到达。
思路分析
换个思路想,我们判断从加油站A到B,如果不能到,我们加之前最大油量的加油站的油,那么问题来了,我们怎么维护前面加油站的油量呢?可以用优先队列,判断不能到B,就取出队加油,如果还不能到,继续加,这样保持加的都是最大加油站的油,直到队列为空,还不到就输出-1
即可。
实现代码
package me.stormma.poj;
import java.util.*;
/**
* 加油站问题 <a href="">题目链接</a>
*
* @author stormma
* @date 2017/10/19
*/
public class Main2431 {
private static int solve(List<Stop> stops, int L, int P) {
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
// ans加油次数,pos当前距起点位置,tank当前
int ans = 0, pos = 0, tank = P;
for (Stop stop : stops) {
// 到下一个加油站的距离
int dis = stop.dis - pos;
// 如果到不了,加油
while (tank < dis) {
if (queue.isEmpty()) {
return -1;
}
// 加经过的加油站最大加油量的
tank += queue.poll();
ans++;
}
tank -= dis;
// 更新当前位置
pos = stop.dis;
// 向优先队列中增加这个加油站的油量
queue.add(stop.tank);
}
return ans;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 加油站数量
int N = in.nextInt();
// 距离终点的距离
List<Stop> stops = new ArrayList<>();
for (int i = 0; i < N; i++) {
stops.add(new Stop(in.nextInt(), in.nextInt()));
}
// 起点到终点的距离
int L = in.nextInt();
// 起始油量数
int P = in.nextInt();
for (Stop stop: stops) {
stop.dis = L - stop.dis;
}
// 终点当做加油站
stops.add(new Stop(L, 0));
Collections.sort(stops, (o1, o2) -> o1.dis - o2.dis);
System.out.println(solve(stops, L, P));
}
static class Stop {
/**加油站距离起始位置的距离*/
int dis;
/**加油站一次可以加的油*/
int tank;
public Stop(int dis, int tank) {
this.dis = dis;
this.tank = tank;
}
}
}