我认为这更像是一个算法问题,但我也想在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)));
谢谢。
答案 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)
我们想要优化的功能是两个行程距离的最小值。找到最小值的最大值与找到产品的最大值相同(没有证明。但要看到这一点,请考虑周长与矩形区域之间的关系。给定周长的区域最大的矩形是正方形,也恰好具有最大的最小边长。)
在下文中,我们将所有权重的总和缩放为1
。因此,像(0.7, 0.3)
这样的分布意味着所有权重的70%都加载到车辆1上。让我们调用车辆1 x
的负载和车辆1-x
的负载。
给定两个线性函数f = a x + b
和g = 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)
这就是您有效解决问题所需的一切。
完整的算法:
查找a
,b
,c
,d
b = vehicleONEMileage(0)
a = (vehicleONEMileage(1) - b) * sum_of_all_weights
c
和d
如上所述计算x_opt
。
x_opt < 0
,将所有重量加载到车辆2 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 ++部分留给您。 ; - )