算法设计与分析:Minimum Number of Refueling Stops(Week 11)
學(xué)號:16340008
題目:871. Minimum Number of Refueling Stops
Question:
A car travels from a starting position to a destination which is target miles east of the starting position.
Along the way, there are gas stations.? Each 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.
The car starts with an infinite tank of gas, which initially has?startFuel?liters of fuel in it.? It uses 1 liter of gas per 1 mile that it drives.
When the car?reaches a gas station, it may stop and refuel, transferring all the gas from the station into the car.
What is the least number of refueling stops the car must make in order to reach its destination?? If it cannot reach the destination, return -1.
Note that if the car reaches a gas station with 0 fuel left, the car can still refuel there.? If the car reaches the destination with 0 fuel left, it is still considered to have arrived.
?
Example 1:
Input: target = 1, startFuel = 1, stations = [] Output: 0 Explanation: We can reach the target without refueling.Example 2:
Input: target = 100, startFuel = 1, stations = [[10,100]] Output: -1 Explanation: We can't reach the target (or even the first gas station).Example 3:
Input: target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]] Output: 2 Explanation: We start with 10 liters of fuel. We drive to position 10, expending 10 liters of fuel. We refuel from 0 liters to 60 liters of gas. Then, we drive from position 10 to position 60 (expending 50 liters of fuel), and refuel from 10 liters to 50 liters of gas. We then drive to and reach the target. We made 2 refueling stops along the way, so we return 2.?
Note:
Answer:
題意大致如下:在起點給定油量startFuel,stations中每個元素[a,b]表示距離起點a處可補充油量b,油量與里程1:1,問最少能加油多少次到距離target的終點(不能則返回-1)。我們可以假定起點為[0,startFuel],于是問題可以化成多個子問題再對比。對于每個油站,我們都當(dāng)成子問題的起點,例如第一個油站stations[0]——[a,b],我們可以當(dāng)成是起點油量為startFuel1 = startFuel0 - a + b,距離終點target1 = target0 - a的子問題。前提是可以從起點到達(dá)第一個油站(即startFuel0 >= a)。
于是對于一個問題,我們作如下操作:
然而在寫代碼的過程中,發(fā)現(xiàn)這樣需要對每次求解子問題創(chuàng)造一個數(shù)組更新起點與加油站的距離,或者記錄該起點與原始起點的距離,這需要修改原遞歸函數(shù)的參數(shù)。而且這種方法將會呈樹狀分散,而且樹的節(jié)點難以重用,因為前面加油方式的改變將改變該次加油的狀態(tài)(剩余油量),顯然沒有發(fā)揮動態(tài)規(guī)劃的優(yōu)點和特性。
再次觀察題目可以發(fā)現(xiàn),實際上題目與背包問題十分類似。0/1背包問題為給定權(quán)重不同的物品,容量定的背包,求能獲得的最大價值。其將問題分為子問題:拿了物品后的剩余物品與容量,不拿物品的剩余物品與容量,取大值(假設(shè)能拿)。此處可以效仿。0/1背包問題用一個二維數(shù)組dp[i][j]存儲在容量為j,面對是否拿第i件物品時能獲得的最大值。此題同樣一個二維數(shù)組,存儲在第i個油站時加j次油能走的最遠(yuǎn)距離,那么在最后一個油站時加最少次油能到target的j值就是所求值。
對于數(shù)組中一個值dp[i][j],我們有:
得到最初代碼(python3):
class Solution:def minRefuelStops(self, target, startFuel, stations):""":type target: int:type startFuel: int:type stations: List[List[int]]:rtype: int"""n = len(stations)if n == 0:if target <= startFuel:return 0else:return -1dp = [[0 for i in range(n + 1)] for i in range(n + 1)]dp[0][0] = startFuelfor i in range(1, n + 1):if startFuel >= stations[i-1][0]:dp[i][0] = startFuelfor i in range(1, n + 1):for j in range(1, i + 1):dp[i][j] = max(dp[i-1][j] if dp[i-1][j] >= stations[i-1][0] else 0, dp[i-1][j-1] + stations[i-1][1] if dp[i-1][j-1] >= stations[i-1][0] else 0)for i in range(n + 1):if dp[n][i] >= target:return ireturn -1然而代碼遇到了TLE:
因為二維數(shù)組其實不必填滿。在上面的代碼中二維數(shù)組是橫向填充,一行一行從左往右從上往下填,時間復(fù)雜度為O(n),然而如果豎向填充,則可能可以在填滿前即可到達(dá)target的情況。
因此把代碼改為豎向填充(實際則交換二層嵌套循環(huán)的i與j),并在每列填充結(jié)束時檢驗?zāi)芊竦竭_(dá)target?,即可應(yīng)付station很多的情況(需要測例不極端,極端則優(yōu)化前后沒有區(qū)別)。
改進(jìn)代碼如下(python3):
class Solution:def minRefuelStops(self, target, startFuel, stations):""":type target: int:type startFuel: int:type stations: List[List[int]]:rtype: int"""n = len(stations)if startFuel >= target:return 0dp = [[0 for i in range(n + 1)] for i in range(n + 1)]dp[0][0] = startFuelfor i in range(1, n + 1):if startFuel >= stations[i-1][0]:dp[i][0] = startFuelfor j in range(1, n + 1):for i in range(j, n + 1):dp[i][j] = max(dp[i-1][j] if dp[i-1][j] >= stations[i-1][0] else 0, dp[i-1][j-1] + stations[i-1][1] if dp[i-1][j-1] >= stations[i-1][0] else 0)if dp[n][j] >= target:return jreturn -1提交結(jié)果如下:
總結(jié)
以上是生活随笔為你收集整理的算法设计与分析:Minimum Number of Refueling Stops(Week 11)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全球十大智能物流装备龙头企业
- 下一篇: java获取微信短链接_微信公众号实现长