C ++:查找可被两组整除的数组项的所有组合

时间:2013-09-04 04:48:52

标签: c++ algorithm

我认为这更像是一个算法问题,但我也想在C ++中做到这一点。 让我用一个例子说明这个问题。

假设我有N个对象(不是编程对象),每个对象具有不同的权重。我有两辆车可以携带它们。车辆足够大,可以随身携带所有物品。这两辆车有自己的里程和油箱中不同的燃油水平。里程也取决于它的重量。

目标是尽可能地使这N个物体。所以我需要在两辆车之间以某种方式分配N个物体。请注意,我不需要将它们带到“相同”的距离,而是尽可能地。例如,我想要两辆车行驶5公里和6公里,而不是一辆行驶2公里,其他行驶7公里。

我无法想到理论上的封闭式计算来确定要加载到每辆车中的重量。因为记住我需要携带所有N个固定值的物体。

据我所知,我需要尝试所有组合。

有人建议使用有效的算法来尝试所有组合吗?

例如,我会有以下内容:

int weights[5] = {1,4,2,7,5}; // can be more values than 5
float vehicelONEMileage(int totalWeight);
float vehicleTWOMileage(int totalWeight);

我怎样才能有效地尝试权重[]与两个函数的所有组合?

两个函数可以假设为线性函数。即两个里程函数的返回值是具有(不同的)负斜率和(不同)偏移的线性函数。

所以我需要找到的是:

MAX(MIN(vehicleONEMileage(x), vehicleTWOMileage(sum(weights) - x)));

谢谢。

2 个答案:

答案 0 :(得分:1)

我可以建议以下解决方案:

组合总数为2 ^(权重数)。使用位逻辑,我们可以遍历所有组合并计算maxDistance。组合值中的位显示哪个重量到哪个车辆。

请注意,算法复杂度是指数级的,int的位数有限!

float maxDistance = 0.f;

for (int combination = 0; combination < (1 << ARRAYSIZE(weights)); ++combination)
{
    int weightForVehicleONE = 0;
    int weightForVehicleTWO = 0;

    for (int i = 0; i < ARRAYSIZE(weights); ++i)
    {
        if (combination & (1 << i)) // bit is set to 1 and goes to vechicleTWO
        {
            weightForVehicleTWO += weights[i];
        }
        else // bit is set to 0 and goes to vechicleONE
        {
            weightForVehicleONE += weights[i];
        }
    }

    maxDistance = max(maxDistance, min(vehicelONEMileage(weightForVehicleONE), vehicleTWOMileage(weightForVehicleTWO)));
}

答案 1 :(得分:1)

  • 这应该在cs或数学网站上。
  • 简化:假设我们可以线性分配权重,而不是一个对象数组。

我们想要优化的功能是两个行程距离的最小值。找到最小值的最大值与找到产品的最大值相同(没有证明。但要看到这一点,请考虑周长与矩形区域之间的关系。给定周长的区域最大的矩形是正方形,也恰好具有最大的最小边长。)

在下文中,我们将所有权重的总和缩放为1。因此,像(0.7, 0.3)这样的分布意味着所有权重的70%都加载到车辆1上。让我们调用车辆1 x的负载和车辆1-x的负载。

给定两个线性函数f = a x + bg = c x + d,其中f是车辆1加载重量x时的里程数,g相同对于车辆2,我们希望最大化

(a*x+b)*(c*(1-x)+d)

让我们来问Wolfram Alpha为我们做的艰苦工作:www.wolframalpha.com/input/?i=derive+%28%28a*x%2Bb%29*%28c*%281-x%29%2Bd% 29%29

它告诉我们

存在极值
x_opt = (a * c + a * d - b * c) / (2 * a * c)

这就是您有效解决问题所需的一切。

完整的算法:

  • 查找abcd

    b = vehicleONEMileage(0)

    a = (vehicleONEMileage(1) - b) * sum_of_all_weights

    cd

  • 相同
  • 如上所述计算x_opt

    • if x_opt < 0,将所有重量加载到车辆2
    • if x_opt > 1,将所有重量加载到车辆1
    • 否则,尝试将tgt_load = x_opt*sum_of_all_weights加载到车辆1上,其余部分加载到车辆2上。
  • 其余的是背包问题。见http://en.wikipedia.org/wiki/Knapsack_problem#0.2F1_Knapsack_Problem

    如何申请?使用那里描述的动态编程算法两次。

    • 最大限度地加载tgt_load
    • 最大化负载(sum_of_all_weights - tgt_load
  • 第一个,如果加载到第一个车辆上,会给你一个分布略低于车辆的分布。

  • 第二个,如果加载到第二辆车上,会给你一个比第二辆车略高于预期的分布。
  • 其中一个是最好的解决方案。比较它们并使用更好的一个。

我将C ++部分留给您。 ; - )