The Gas Station Problem – fast implementation

Problem Detail: Recently I was asking about the algorithm to solve The Gas Station Problem and I got useful answer. Unfortunately solution with transforming a graph to complete graph and then preparing another one to find the shortest path (as described in paragraph 4) is really slow in case of my constraints. I figured out how to implement much faster version. It’s way better, but has a bottleneck :-(. Let me first describe my implementation. It’s really simple: I use BFS and relaxation method to calculate D[destination][0]:

D[v][f] - minimum cost to get from u to v with remaining f units of fuel at this city.  minFuel - minimum remaining fuel at v = max(0, f1 - distance(u,v)) maxFuel - maximum remaining fuel at v = tankCapacity - distance(u,v)  D[source][0] = 0 D[v][f] = min((u,v), f1, f2 | u->v in Edges and f1 in 0..tankCapacity and f2 in minFuel..maxFuel)              { D[u][f1] + (f2 - f1 + distance(u,v)) * fuelRate[u] } 

The bottleneck is because of going through all possible values (f1, f2). Pseudocode:

queue.push(source); D[source][0] = 0 visited[source] = true  while(!queue.empty)     current = queue.pop      foreach (current,v) in Edges        if !visited[v]            queue.push(v)            visited[v] = true          for f1 in 0..tankCapacity            if D[current][f1] == infinity               continue              minFuel = max(0, f1 - distance[current,v])             maxFuel = tankCapacity - distance[current,v]              for f2 in minFuel..maxFuel                 toRefill = f2 - f1 + distance[current,v]                 newCost =  D[current][f1] + toRefill * fuelRate[current]                 if (newCost < D[v][f2])                    D[v][f2] = newCost   return D[destination][0] 

Constraints (only integers):

maximum vertices:      1000 maximum edges:         10000 maximum distance:      100 maximum fuel rate:     100 maximum tank capacity: 100 

Does anybody have an idea how to improve this algorithm to make it faster?

Asked By : Wojciech Kulik

Answered By : Wojciech Kulik

Finally I had prepared a solution with good enough complexity. Friend from my college had given me some hints and I managed to implement it. Maybe it will help someone, so I decided to describe this solution here. The idea is very simple, we use Dijkstra’s Algorithm, but instead simple vertices we have pairs (v, f). v – vertex id, f – fuel in tank. This solution is much faster, because we don’t need to go through all values of “f” and also when we process a vertex, it already has an optimal solution. So when we’ll get to the destination vertex, we can stop further processing. Dijkstra’s Algorithm needs to get a minimum value in each iteration, so it’s good to use heap structure for a priority queue. Pseudocode:

D[v][f]        - minimum cost to get from source to v with f units of fuel distance[u][v] - distance between u and v   relax(tankCapacity, u, f, newCost):     if (f >= 0 and f <= tankCapacity and D[u][f] > newCost)         D[u][f] = newCost         heap_push_or_update(D[u][f])   solve(tankCapacity, source, destination):     foreach (v, f)         D[v][f] = infinity      D[source][0] = 0     heap_push(D[source][0])      while not heap_empty()         (v, f) = heap_pop_min();          //don't go further than destination         if (v == destination and f == 0)             return D[v][0];          //stay in the city and refill more fuel - it can improve D[v][f + 1]         newCost = D[v][f] + fuelRate[v];         relax(tankCapacity, v, f + 1, newCost);          //go to the adjacent cities "u" without refilling - it can improve D[u][f - d]           foreach (v, u) in Edges             relax(tankCapacity, u, f - distance[v][u], D[v][f]); 

Best Answer from StackOverflow

Question Source : http://cs.stackexchange.com/questions/25968

Leave a Reply