Minimum refueling times

Keywords: Algorithm leetcode Dynamic Programming

Title: the car starts from the starting point to the destination, which is located at the target mile east of the starting position.

There are gas stations along the way. Each station[i] represents a gas station. It is located at station[i][0] miles east of the starting position, and there are station[i][1] liters of gasoline.

Suppose that the capacity of the car's fuel tank is unlimited, in which there is initially startFuel liters of fuel. It uses a liter of gasoline every mile.

When the car arrives at the gas station, it may stop to refuel and transfer all gasoline from the gas station to the car.

What is the minimum number of times a car needs to refuel in order to reach its destination? If the destination cannot be reached, - 1 is returned.

Note: if the remaining fuel is 0 when the car arrives at the gas station, it can still refuel there. If the remaining fuel is 0 when the car reaches its destination, it is still considered to have reached its destination.

Example 1:

Input: target = 1, startFuel = 1, stations = []
Output: 0
Explanation: we can reach our destination without refueling.

Source: LeetCode
Link: https://leetcode-cn.com/problems/minimum-number-of-refueling-stops

Solution 1: DP

Analysis: suppose we refuel for i times and the current maximum distance is s, such as:

target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]]

Then, if we only refuel once, we can run 10 + 60 = 70 as far as possible

If twice, then 10 + 60 + 40 = 110

Then, let dp[i] be the longest distance that can be reached by refueling I times, and s be the oil newly added to the gas station
d p [ i ] = m a x { d p [ i ] , d p [ i ] + s } dp[i]=max\{dp[i],dp[i]+s\} dp[i]=max{dp[i],dp[i]+s}
Code implementation:

func minRefuelStops(target int, startFuel int, stations [][]int) int {
	dp := make([]int, len(stations)+1)
	dp[0] = startFuel
	// Traverse to each node
	for i, station := range stations {
		// Currently, it can be added up to i times
		// dp[i+1]=max(dp[i+1],dp[i]+s)
		// This can only be from the back to the front,
		// Because if you join I this site from the front to the back, it will cause this point to be used many times and change dp[i]
		for k := i; k >= 0; k-- {
			// If you can get there so many times, you can choose this gas station
			if dp[k] >= station[0] {
				dp[k+1] = max(dp[k+1], dp[k]+station[1])
			}
		}

	}
	for i, v := range dp {
		if v >= target {
			return i
		}
	}
	return -1
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

Solution 2: maximum heap + greed

Analysis: assuming that we expect to arrive at the next station, it is possible that the current oil can or cannot arrive. If it cannot arrive, we need to refuel at the station that can add the most oil when passing by until it can arrive. If each station has been added or cannot arrive, return - 1

Code implementation:

func minRefuelStops(target int, startFuel int, stations [][]int) int {
	var qp []int
	res := 0

	nowTank := startFuel
	for _, station := range stations {
		if nowTank < station[0] {
			// Select multiple passing stations
			if len(qp) == 0 {
				return -1
			}
			c:=0
			for r:=0;r<len(qp);r++{
				nowTank += qp[r]
				res++
				c++
				if nowTank>=station[0]{
					break
				}
			}
			qp=qp[c:]
		}
		if nowTank >= station[0] {
			qp = append(qp, station[1])
			sort.Slice(qp, func(i, j int) bool {
				return qp[i] > qp[j]
			})
		} else {
			return -1
		}
	}
	if nowTank >= target {
		return res
	}
	for i := 0; i < len(qp); i++ {
		nowTank += qp[i]
		res++
		if target <= nowTank {
			return res
		}
	}

	return -1

}

Posted by jokerofsouls on Sat, 09 Oct 2021 02:42:46 -0700