日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法设计与分析:Minimum Number of Refueling Stops(Week 11)

發(fā)布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法设计与分析:Minimum Number of Refueling Stops(Week 11) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

學(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:

  • 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

  • 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)。

    于是對于一個問題,我們作如下操作:

  • 檢查能否直接到達(dá)終點,可以則直接返回0
  • 檢查從起點有沒有可以到達(dá)的油站,如果沒有則返回油站數(shù)+1(方便直接比較加油次數(shù)),有則記錄每個可達(dá)油站
  • 對每個可達(dá)油站,建立子問題,其startFuel = startFuel - a + b,target = target - a,對每個子問題執(zhí)行步驟1、2、3,對它們的返回數(shù)取最小值+1并返回。
  • 然而在寫代碼的過程中,發(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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。