生命不息,奮鬥不止!
@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;
}
}
}