<p>tl;dr: By following the paper mentioned in the comments, a C# implementation of a solver (below) handles the case of 500 randomly distributed stations in about 14 ms on an aging laptop, so in particular, this handles the 100 station case easily, and is orders of magnitude faster than using a MIP solver, as suggested in the comments.</p>

<p>Typically, the gas station problem (which we should really start calling the charging station problem, but that's a different story) assumes that the starting fuel amount is 0: The more general case may be reduced to the 0 case by adding a new starting station with free fuel at a distance to your initial starting point that causes the car to reach your initial starting point with a tank containing your given amount of fuel. This can be done without ruining the general complexity of the solution below.</p>

<p>Noting this, the problem boils down to that described in <a href="http://www.cs.umd.edu/users/samir/grant/gas-j.pdf" rel="nofollow noreferrer"><em>To Fill or not to Fill: The Gas Station Problem</em></a>, as <a href="https://stackoverflow.com/questions/58289424/gas-station-problem-cheapest-and-least-amount-of-stations/58463200#comment102944110_58289424">noted by @PySeeker</a> in the comments. In particular, $O(N \log N)$ seems optimistic. In the paper, the relevant theorem handles your case in $O(\Delta N^2 \log N)$, where $\Delta$ is minimum number of stops required (which you can easily precompute in linear time if necessary). Another paper, <em><a href="https://arxiv.org/abs/1706.00195" rel="nofollow noreferrer">A fast algorithm for the gas station problem</a></em>, describes how to solve the problem in $O(\Delta N^2 + N^2 \log N)$, but let's just focus on the former paper here.</p>

<p>Its Theorem 2.2 solves the problem for a fixed $\Delta$, where you're really only interested in the lowest possible one. Since their recurrence is set up to solve the problem for increasing $\Delta$, this amounts to simply halt the algorithm once $A(s, \Delta, 0)$, in the notation of the paper, becomes finite.</p>

<p>Note also that compared to the general problem which handles general graphs whose edge weights form a metric (a requirement noted in the second of the above-mentioned papers but for some reason not in the first one), your situation is simpler with vertices $0, \dots, N - 1$ and distances $d_{uv} = d[v] - d[u]$.</p>

<p>One thing to be a bit careful when implementing the algorithm is that while the description in the paper is fine, the pseudo-code is rather buggy/lacking (cf. e.g. <a href="https://cs.stackexchange.com/q/115930/108166">this question</a>). Below we implement the various fixes needed to get the algorithm up and running, as well as a some amount of indexing to help improve performance.</p>

<p>You mention in your edit that besides the value of the optimal solution, you would also like to get the actual paths taken. The algorithm below only outputs the value, i.e. $A(0, \Delta, 0)$, but by keeping track of the argmin in a separate table whenever the table of values is updated, you'll immediately get the desired path as well. This is completely analogous to how you would implement e.g. Dijkstra's algorithm.</p>

<p>You don't specify a language in the question, so I took the liberty of writing this in C#; the code is very C'y, so it should be straightforward to port it to Java if necessary (s/List/ArrayList/g). The notation follows the paper, so let me simply refer to that for comments/documentation (but let me also apologize that without the paper at hand, the implementation is likely impossible to read).</p>

<p>The solution doesn't go all the way: As mentioned above, a different algorithm with better complexity exists, and it would be natural to try that one as well; it's not particularly complicated. Moreover, the implementation at hand has a natural performance optimization that's not included: It's not necessary to grow the table for all $q$; for example, the source vertex $u = 0$ will depend only on the previous row through <code>R[0]</code>, so by precomputing the minimal value of $\Delta$, we can avoid some redundant calculation.</p>

<pre class="lang-cs prettyprint-override"><code>private static double Solve(double[] c, double[] d, double U)
{
    int n = d.Length;
    int t = n - 1;
    var R = new int[n][];
    var indep = new double[n][];
    var GV = new List&lt;List&lt;double&gt;&gt;();
    var GVar = new List&lt;Dictionary&lt;int, int&gt;&gt;();
    for (int u = 0; u &lt; n; u++)
    {
        var l = new List&lt;int&gt;();
        for (int v = u + 1; v &lt; n; v++)
        {
            if (d[v] - d[u] &lt;= U)
                l.Add(v);
            else break;
        }

        R[u] = l.ToArray();
        indep[u] = new double[l.Count];
    }

    for (int u = 0; u &lt; n; u++)
    {
        var l = new List&lt;double&gt; { 0 };
        var gvar = new Dictionary&lt;int, int&gt;();
        int i = 1;
        for (int w = 0; w &lt; u; w++)
        {
            if (c[w] &lt; c[u] &amp;&amp; d[u] - d[w] &lt;= U)
            {
                l.Add(U - (d[u] - d[w]));
                gvar[w] = i++;
            }
        }

        GV.Add(l);
        GVar.Add(gvar);
    }

    int q = 0;
    var Cq1 = new double[n][];
    var Cq2 = new double[n][];
    for (int i = 0; i &lt; n; i++)
    {
        Cq1[i] = new double[GV[i].Count];
        Cq2[i] = new double[GV[i].Count];
        for (int j = 0; j &lt; GV[i].Count; j++)
        {
            Cq1[i][j] = double.PositiveInfinity;
            Cq2[i][j] = double.PositiveInfinity;
        }
    }

    var toggle = true;
    while (true)
    {
        var Cq = toggle ? Cq1 : Cq2;
        var prev = !toggle ? Cq1 : Cq2;
        toggle = !toggle;
        for (int i = 0; i &lt; n; i++)
        {
            for (int j = 0; j &lt; GV[i].Count; j++)
                Cq[i][j] = double.PositiveInfinity;
        }
        for (int u = 0; u &lt; n; u++)
        {
            Grow(u, q, t, c, d, U, R[u], GV[u], q == 0 ? null : prev, Cq, indep[u], GVar);
            if (u == 0 &amp;&amp; !double.IsPositiveInfinity(Cq[u][0]))
                return Cq[u][0];
        }
        q++;
    }
}

private static void Grow(int u, int q, int t, double[] c, double[] d, double U,
        int[] r, List&lt;double&gt; gv, double[][] prev, double[][] ret, double[] indep,
        List&lt;Dictionary&lt;int, int&gt;&gt; GVar)
{
    double cost = c[u];
    if (q == 0 || u == t)
    {
        for (int i = 0; i &lt; gv.Count; i++)
        {
            var g = gv[i];
            if (q == 0 &amp;&amp; g &lt;= d[t] - d[u] &amp;&amp; d[t] - d[u] &lt;= U)
                ret[u][i] = (d[t] - d[u] - g) * cost;
        }
        return;
    }

    for (var i = 0; i &lt; r.Length; i++)
    {
        var v = r[i];
        indep[i] = c[v] &lt;= cost ? prev[v][0] + (d[v] - d[u]) * cost : prev[v][GVar[v][u]] + U * cost;
    }

    Array.Sort(indep, r);
    var j = 0;
    var w = r[j];
    for (int gi = 0; gi &lt; gv.Count; gi++)
    {
        var g = gv[gi];
        while (g &gt; d[w] - d[u] &amp;&amp; c[w] &lt;= cost)
        {
            j++;
            if (j == r.Length) return;
            w = r[j];
        }

        ret[u][gi] = indep[j] - g * cost;
    }
}
</code></pre>

<p>Example usage, and benchmark on a 500 station case:</p>

<pre class="lang-cs prettyprint-override"><code>static void Main(string[] args)
{
    var rng = new Random();
    var sw = new Stopwatch();
    for (int k = 0; k &lt; 100; k++)
    {
        int n = 500;
        var prices = Enumerable.Range(1, n).Select(_ =&gt; rng.NextDouble()).ToArray();
        var distances = Enumerable.Range(1, n).Select(_ =&gt; rng.NextDouble() * n).OrderBy(x =&gt; x).ToArray();
        var capacity = 15;
        sw.Start();
        var result = Solve(prices, distances, capacity);
        sw.Stop();
        var time = sw.Elapsed;
        Console.WriteLine($"{time} {result}");
        sw.Reset();
    }
}
</code></pre>
Gas Station Problem - cheapest and least amount of stations
<p>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.</p>

<p>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.</p>

<p>How my algorithm works:</p>

<ul>
<li>Go to the tank stations that are available from the start (the 22l in the example)</li>
<li>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.</li>
<li>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$</li>
</ul>

<p>The problems I still have:</p>

<ul>
<li><p>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.</p></li>
<li><p>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.</p></li>
</ul>

<p>Extra notes:</p>

<ul>
<li>Arriving at a gas station with 0 liters of fuel counts as having arrived.  </li>
<li>EDIT: All paths of the same price and least amount of stations must be found.</li>
</ul>

<p>My current code (snippet) I think that the methods names are self explanitory, add comment if they are not., </p>

<pre><code>    void findRoutes(List&lt;GasStation&gt; reachableStations, List&lt;GasStation&gt; previousStations) {
        int currentSteps = previousStations.size();
        if (currentSteps &gt; leastSteps) {
            return;
        }
        // Reached the end (reachableStations will be null if it can reach the end)
        if (reachableStations == null) {
            // less steps
            if (currentSteps &lt; 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 &gt; leastSteps) {
            return;
        }
        // Check those further away so we get a smaller step amount quicker
        Collections.reverse(reachableStations);
        for (GasStation reachableStation : reachableStations) {
            List&lt;GasStation&gt; newPrevious = new LinkedList&lt;&gt;(previousStations);
            newPrevious.add(reachableStation);
            findRoutes(reachableStation.getReachableGasStations(), newPrevious);
        }
    }
</code></pre>