I am working on a problem that consists of the following: You are driving a car with a certain fuel usage m (in our example we will take 8l/100km) and you are driving a straight of length x (example: 1000km). The car starts out with a certain amount of fuel f (example: 22l). Your car has a fuel tank of size g (example: 55l) and there are gas stations (which have a price per liter) plotted around the straight (e.g 100km (1.45$/l), 400km(1.40$/l) and 900km(1.22$/l). The aim of the algorithm I'm having a hard time creating is: With the least amount of stops (so not the cheapest route, but the one with the least stops at gas stations) find the cheapest way and tell the user how much liters he has to tank at which gas station and how much it will cost.
Currently using recursion and for loops (presumably O(n^2)) I've created an algorithm that can solve some problems up to a certain complexity, it starts to struggle when there are about 100 gas stations.
How my algorithm works:
- Go to the tank stations that are available from the start (the 22l in the example)
- Go to each tank station and list the tank stations (or the end) in range by having a full tank (since the car can fuel up at the tank station you can have a full tank) I do save this in a list so it's not calculated twice.
- Then for loop every one of those tank stations that can be reached and recursion occurs, pretty much I then save the smallest amount of stops required and rinse and repeat and voila I get the smallest answer which is (in our example) stopping at 100 fueling 10.00 liters, paying 14.5$ and then stopping at 400 fueling 48 liters and paying 67.20$
The problems I still have:
How (Is it even possible)can I reduce the complexity to O(N log N) or linear, so that all (even if it's 100+ gas stations) can be checked. At the moment the recursive methods go down to 10+ recursions in recursions which makes anything above 100 gas stations pretty much unsolvable for this algorithm.
At the moment my algorithm only fuels up as much as it requires to reach the next gas station or the end: What's the best way to handle the problem if the first gas station is cheaper than the second and you can fuel up "n liters more" so you buy less liters at the second gas station. Since in the ideal case you have 0 liters left at the end of the trip.
Extra notes:
- Arriving at a gas station with 0 liters of fuel counts as having arrived.
- EDIT: All paths of the same price and least amount of stations must be found.
My current code (snippet) I think that the methods names are self explanitory, add comment if they are not.,
void findRoutes(List<GasStation> reachableStations, List<GasStation> previousStations) {
int currentSteps = previousStations.size();
if (currentSteps > leastSteps) {
return;
}
// Reached the end (reachableStations will be null if it can reach the end)
if (reachableStations == null) {
// less steps
if (currentSteps < leastSteps) {
routes.clear();
routes.add(previousStations);
leastSteps = previousStations.size();
return;
} else {
// same amount of steps
routes.add(previousStations);
return;
}
}
// would be too many steps
if (currentSteps + 1 > leastSteps) {
return;
}
// Check those further away so we get a smaller step amount quicker
Collections.reverse(reachableStations);
for (GasStation reachableStation : reachableStations) {
List<GasStation> newPrevious = new LinkedList<>(previousStations);
newPrevious.add(reachableStation);
findRoutes(reachableStation.getReachableGasStations(), newPrevious);
}
}