Align Cars Using Minimum Cost

You are the owner of a car gallery, and the vehicles you’ve ordered for the fancy car show has arrived. You have N cars each of length F feet. The ‘i’th car is located at position X(i) feet from your store on a road. However, the cars aren’t organized properly. You’ve allocated a strip of road from location A feet to location B feet, [A, B] to keep these cars. You want to align the cars all in a row without gaps.
This means, that the cars should be located at positions Y, Y + L, Y + 2L, Y + 3L … Y + (N – 1)L such that A <= Y < Y + NL <= B. The order of the cars does not matter.
You can use your tow truck to move the cars from their current location. Moving a car by one foot uses 1 unit of petrol. Output the minimum amount of petrol you would have to spend to align the vehicles properly.

Examples:

Input : N = 3, F = 4, 
        A = 11, B = 23
        X = [10, 11, 30]
Output : 16
We can keep the second car at its current 
position 10.
So we move the first car to position 15.
We then drag the third car from position 30
to position 19.
(15 - 10) + (30 - 19) = 16

Input  : N = 3, F = 6
         A = 10, B = 30
         X = [10, 20, 30]
Output : 10
We can move the first car to 12.
We can move the second car to position 18.
We then move the third car to position 24.
(12 - 10) + (20 - 18) + (30 - 24) = 10

We can see that by selecting a starting position in [A, B – N * F] for the line of vehicles to start at, the positions of all the other vehicles becomes set, since they have to be in a line without gaps.
We can also see that calculating a minimum petrol usage of an arrangement starting at a position X can be calculated by placing the first car at the first position, second car at the second position, and so on.

Thus, our problem reduces to finding a starting position in [A, B – N * F] having minimum petrol usage.

Naive Implementation
We can go through each position from A to B – N * F and calculate the amount of petrol used in each case. We can then find the minimum among all of these.

Time complexity of this method becomes O(N * (B – N * F – A)) or if we assume B – A ~ c * N, then O(N ^ 2).

Optimized Implementation
If we output the costs of the above implementation, we can notice a trend where the amount of petrol used decreases, reaches a minimum, then proceeds to increase again. Thus, we can optimize the above algorithm using binary search.

We select the middle of the possible positions.
We then calculate the amount of petrol used starting at that position, and for the position one foot behind it.
If the cost of the position behind it is more, we are approaching the minimum.
If the cost is less, then we have already crossed it.
Thus by using these as conditions in the binary search, we get an optimized approach.

// Program to calculate minimum petrol to
// place cars in a line
#include <vector>
#include <iostream>
#include <algorithm>
#include <limits.h>
using namespace std;
#define ull unsigned long long

// Function to calculate cost of arranging cars
ull calculate(vector<ull> cars, ull F, ull pos)
{
    // Place each car and calculate cost
    ull cost = 0;
    for (ull i = 0; i < cars.size(); ++i)
        cost += abs((long long)cars[i] - (long long)(pos + i * F));
    return cost;
}

ull getMinPetrol(vector<ull> cars, ull N, ull F,
                 ull start, ull end, ull minimum = -1)
{
    // Finished binary searching
    if (start > end)
        return minimum;

    // Set middle element
    ull mid = (start + end) / 2;

    // Calculate cost at two points
    ull count = calculate(cars, F, mid);
    ull count2 = calculate(cars, F, mid + 1);

    // Bounds exceeded
    if (count == -1) {
        end = mid - 1;
        return getMinPetrol(cars, N, F, start,
                            end, minimum);
    }

    // Set bounds and recurse
    if (count < minimum) 
        minimum = count;
    
    if (count2 > count)
        end = mid - 1;
    else
        start = mid + 1;
    return getMinPetrol(cars, N, F, start, end, minimum);
}

// Driver function
int main()
{
    ull N = 3, F = 4, A = 11, B = 23;
    vector<ull> cars = { 10, 11, 30 };
    ull end = B - N * F;
    cout << getMinPetrol(cars, N, F, A, end) << "\n";

    N = 3, F = 6, A = 10, B = 30;
    vector<ull> cars2 = { 10, 20, 30 };
    end = B - N * F;
    cout << getMinPetrol(cars2, N, F, A, end) << "\n";
}

Output:

16
10

Time Complexity = O(N * log(B – A – N * F)) or O(NlogN) if we assume B – A ~ cN.

This article is contributed by Aditya Kamath. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice

Recommended Posts:







Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.