微软面试题: 最低加油站数量
描述
汽车从起始位置行驶到目的地,该目的地位于起始位置以东的目标英里处。
一路上,有加油站。 每个station[i]代表一个加油站,它位于起始位置以东station[i] [0]英里处,并且有station[i] [1]升汽油。
汽车开始时有一个无限的汽油罐,最初燃料中含有燃料。 它每1英里就会使用1升汽油。
当汽车到达加油站时,它可能停下来并加油,将所有汽油从车站转移到汽车中。
为了到达目的地,汽车必须加油的最少次数是多少? 如果无法到达目的地,则返回-1。
请注意,如果汽车到达加油站时燃料正好为0,汽车仍然可以在那里加油。 如果汽车在剩余0燃料的情况下到达目的地,仍然认为已经到达。
1 <= target, startFuel, stations[i][1] <= 10^9
0 <= stations.length <= 500
0 < stations[0][0] < stations[1][0] < … < stations[stations.length-1][0] < target
在线评测地址
样例1
输入: target = 1, startFuel = 1, stations = []
输出: 0
解释:到达目标地点无需进入任何加油站.
样例2
输入: target = 100, startFuel = 1, stations = [[10,100]]
输出: -1
解释: 无法到达目标地点 (甚至连第一个加油站也到不了).
样例3
输入: target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]]
输出: 2
解释:
开始时我们有10升汽油.
行驶至10公里处,消耗10升汽油,并在加油站将汽油从0补充至60升。
然后我们从10公里处移动至60公里处(消耗50升汽油),
并在加油站把汽油从10升补充至50升,然后到达目标地点。
我们在过程中停下并加油了2次,所以返回2.
解题思路
采用动态规划的思想,将起点,l个加油站,以及终点分别按1 ~ l + 2进行编号。 dpi表示车在第i个站点时,若之前已经停留过j次,当前所保留的最多汽油升数。 若到达某个站点时,当前气体足以到达下个站点时,有动态转移方程: dpi + 1 = max(dpi + 1, dpi-(ai + 1 - ai))。 若当前气体加上该站点气体足以到达下个站点时,有动态转移方程: dpi + 1 = max(dpi + 1,dpi + bi - (ai + 1 - ai))。 最后寻找最小的i使得dpn的值存在,i即可最小停靠加油的次数。
源代码
public class Solution {
/**
* @param target: the distance of src and the dst
* @param startFuel: the init fuel
* @param stations: station[i] represents a gas station that is station[i][0] miles east of the starting position, and has station[i][1] liters of gas.
* @return: the minimun number
*/
public int minimumNumberofRefuelingStops(int target, int startFuel, List<List<Integer>> stations) {
int l = stations.size();
int dp[][] = new int[1050][1050];
int a[] = new int[1050];
int b[] = new int[1050];
int i,j,n;
for (i = 0;i < 1050;i++){
for (j = 0; j < 1050;j++){
dp[i][j] = -1;
}
}
dp[1][0]=startFuel;
a[1]=0;
for (i=0;i<l;i++) {
a[i+2]=stations.get(i).get(0);
b[i+2]=stations.get(i).get(1);
}
a[l+2]=target;n=l+2;
for (i=1;i<=l+2;i++)
for (j=0;j<=i;j++) if (dp[i][j]!=-1) {
if (dp[i][j]>=a[i+1]-a[i]) {
dp[i+1][j]=Math.max(dp[i+1][j],dp[i][j]-(a[i+1]-a[i]));
}
if (dp[i][j]+b[i]>=a[i+1]-a[i]) {
dp[i+1][j+1]=Math.max(dp[i+1][j+1],dp[i][j]+b[i]-(a[i+1]-a[i]));
}
}
for (i=0;i<=n;i++) if (dp[n][i]!=-1) return i;
return -1;
// Write your code here.
}
}