📜  使用最低成本调整汽车

📅  最后修改于: 2022-05-13 01:57:13.727000             🧑  作者: Mango

使用最低成本调整汽车

您是一家汽车画廊的老板,您为豪华车展订购的车辆已经到货。你有 N 辆车,每辆车长 F 英尺。第 'i' 辆车位于距离您的商店在路上 X(i) 英尺的位置。然而,汽车没有得到妥善安排。您已经分配了一条从位置 A 英尺到位置 B 英尺的道路,[A, B] 来保留这些汽车。您希望将汽车排成一排而没有间隙。
这意味着,汽车应该位于位置 Y, Y + L, Y + 2L, Y + 3L ... Y + (N – 1)L 使得 A <= Y < Y + NL <= B。汽车无所谓。
您可以使用拖车将汽车从当前位置移走。一英尺移动一辆车使用 1 单位汽油。输出您必须花费的最小汽油量才能正确对齐车辆。

例子:

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

我们可以看到,通过在 [A, B – N * F] 中选择一个起始位置作为车辆开始的位置,所有其他车辆的位置都设置好了,因为它们必须在一条没有间隙的直线上。
我们还可以看到,可以通过将第一辆车放在第一个位置,将第二辆车放在第二个位置,依此类推来计算从位置 X 开始的布置的最小汽油使用量。

因此,我们的问题简化为在 [A, B – N * F] 中找到一个具有最少汽油使用量的起始位置。



幼稚的实现
我们可以遍历从 A 到 B – N * F 的每个位置,并计算每种情况下使用的汽油量。然后我们可以找到所有这些中的最小值。

这种方法的时间复杂度变为 O(N * (B – N * F – A)) 或者如果我们假设 B – A ~ c * N,那么 O(N ^ 2)。

优化实施
如果我们输出上述实施的成本,我们可以注意到一个趋势,即使用的汽油量减少,达到最小值,然后再次增加。因此,我们可以使用二分搜索来优化上述算法。

我们选择可能位置的中间位置。
然后,我们计算从该位置开始以及其后一英尺位置使用的汽油量。
如果后面持仓的成本更多,我们就接近最小值了。
如果成本更低,那么我们已经越过了它。
因此,通过在二分搜索中使用这些作为条件,我们得到了一种优化方法。

// Program to calculate minimum petrol to
// place cars in a line
#include 
#include 
#include 
#include 
using namespace std;
#define ull unsigned long long
  
// Function to calculate cost of arranging cars
ull calculate(vector 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 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 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 cars2 = { 10, 20, 30 };
    end = B - N * F;
    cout << getMinPetrol(cars2, N, F, A, end) << "\n";
}

输出:

16
10

时间复杂度 = O(N * log(B – A – N * F)) 或 O(NlogN) 如果我们假设 B – A ~ cN。