Open In App

Align Cars Using Minimum Cost

Improve
Improve
Like Article
Like
Save
Share
Report

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 two 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 11.
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. 
 

CPP




// Program to calculate minimum petrol to
// place cars in a line
#include <algorithm>
#include <iostream>
#include <limits.h>
#include <vector>
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";
}


Java




// Program to calculate minimum petrol to
// place cars in a line
public class Solution
{
   
  // Function to calculate cost of arranging cars
  static int calculate(int[] cars, int F, int pos)
  {
     
    // Place each car and calculate cost
    int cost = 0;
    for (int i = 0; i < cars.length; ++i)
      cost += Math.abs(cars[i] - (pos + i * F));
    return cost;
  }
 
  static int minimum;
  static int getMinPetrol(int[] cars, int N, int F,
                          int start, int end)
  {
     
    // Finished binary searching
    if (start > end)
      return minimum;
 
    // Set middle element
    int mid = (start + end) / 2;
 
    // Calculate cost at two points
    int count = calculate(cars, F, mid);
    int count2 = calculate(cars, F, mid + 1);
 
    // Bounds exceeded
    if (count == -1) {
      end = mid - 1;
      return getMinPetrol(cars, N, F, start, end);
    }
 
    // 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);
  }
 
  public static void main(String[] args)
  {
    int N = 3, F = 4, A = 11, B = 23;
    int[] cars = { 10, 11, 30 };
    int end = B - N * F;
    minimum = Integer.MAX_VALUE;
    System.out.println(
      getMinPetrol(cars, N, F, A, end));
 
    N = 3;
    F = 6;
    A = 10;
    B = 30;
    int[] cars2 = { 10, 20, 30 };
    end = B - N * F;
    minimum = Integer.MAX_VALUE;
    System.out.println(
      getMinPetrol(cars2, N, F, A, end));
  }
}
 
// This code is contributed by karandeep1234.


Python3




# Function to calculate the total cost of arranging cars at given positions
def calculate(cars, F, pos):
    cost = 0
    for i in range(len(cars)):
        cost += abs(cars[i] - (pos + i * F))
    return cost
 
# Function to find the minimum petrol required to arrange cars optimally
def getMinPetrol(cars, N, F, start, end, minimum=float('inf')):
    # Base case: if the start position is greater than the end position, return the minimum
    if start > end:
        return minimum
     
    # Find the middle position
    mid = (start + end) // 2
 
    # Calculate the cost for the current position and the next position
    count = calculate(cars, F, mid)
    count2 = calculate(cars, F, mid + 1)
 
    # Update the minimum cost if the current cost is lower
    if count < minimum:
        minimum = count
 
    # Adjust the search space based on the cost of the current and next positions
    if count2 > count:
        end = mid - 1
    else:
        start = mid + 1
 
    # Recursively call the function with the updated search space
    return getMinPetrol(cars, N, F, start, end, minimum)
 
# Driver function
if __name__ == "__main__":
    # Test case 1
    N = 3
    F = 4
    A = 11
    B = 23
    cars = [10, 11, 30]
    end = B - N * F
    print(getMinPetrol(cars, N, F, A, end))
 
    # Test case 2
    N = 3
    F = 6
    A = 10
    B = 30
    cars2 = [10, 20, 30]
    end = B - N * F
    print(getMinPetrol(cars2, N, F, A, end))


C#




using System;
 
public class Solution {
    // Function to calculate cost of arranging cars
    static int Calculate(int[] cars, int F, int pos)
    {
        // Place each car and calculate cost
        int cost = 0;
        for (int i = 0; i < cars.Length; ++i)
            cost += Math.Abs(cars[i] - (pos + i * F));
        return cost;
    }
 
    static int minimum;
 
    static int GetMinPetrol(int[] cars, int N, int F,
                            int start, int end)
    {
        // Finished binary searching
        if (start > end)
            return minimum;
 
        // Set middle element
        int mid = (start + end) / 2;
 
        // Calculate cost at two points
        int count = Calculate(cars, F, mid);
        int count2 = Calculate(cars, F, mid + 1);
 
        // Bounds exceeded
        if (count == -1) {
            end = mid - 1;
            return GetMinPetrol(cars, N, F, start, end);
        }
 
        // 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);
    }
 
    public static void Main(string[] args)
    {
        int N = 3, F = 4, A = 11, B = 23;
        int[] cars = { 10, 11, 30 };
        int end = B - N * F;
        minimum = int.MaxValue;
        Console.WriteLine(GetMinPetrol(cars, N, F, A, end));
 
        N = 3;
        F = 6;
        A = 10;
        B = 30;
        int[] cars2 = { 10, 20, 30 };
        end = B - N * F;
        minimum = int.MaxValue;
        Console.WriteLine(
            GetMinPetrol(cars2, N, F, A, end));
    }
}


Javascript




// Function to calculate cost of arranging cars
function calculate(cars, F, pos) {
    // Place each car and calculate cost
    let cost = 0;
    for (let i = 0; i < cars.length; ++i)
        cost += Math.abs(cars[i] - (pos + i * F));
    return cost;
}
 
// Function to find the minimum petrol needed to place cars in a line
function getMinPetrol(cars, N, F, start, end, minimum = Infinity) {
    // Finished binary searching
    if (start > end)
        return minimum;
 
    // Set middle element
    let mid = Math.floor((start + end) / 2);
 
    // Calculate cost at two points
    let count = calculate(cars, F, mid);
    let 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
function main() {
    // Test case 1
    let N1 = 3, F1 = 4, A1 = 11, B1 = 23;
    let cars1 = [10, 11, 30];
    let end1 = B1 - N1 * F1;
    console.log(getMinPetrol(cars1, N1, F1, A1, end1));
 
    // Test case 2
    let N2 = 3, F2 = 6, A2 = 10, B2 = 30;
    let cars2 = [10, 20, 30];
    let end2 = B2 - N2 * F2;
    console.log(getMinPetrol(cars2, N2, F2, A2, end2));
}
 
// Run the program
main();


Output: 
 

16
10

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

 



Last Updated : 02 Feb, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads