【问题标题】:Hungarian algorithm with multiple assignments具有多个分配的匈牙利算法
【发布时间】:2015-06-15 09:57:07
【问题描述】:

假设我们有 N 个工作和 K 个工人来完成这些工作。但是对于某些工作,我们需要 2 名员工,而对于某些工作,我们只需要一名。员工也不能做所有的工作。例如,工人 1 可以做工作 1,2 和 5,而不能做工作 3 和 4。此外,如果我们雇用工人 1 做工作 1,那么我们希望他做工作 2 和 5,因为我们已经付给了他工资。

例如,假设我们有 5 个工作和 6 个工人。对于工作 1,2 和 4,我们需要 2 个男人,而对于工作 3 和 5,我们只需要一个。这是每个工人可以做的工作清单和他需要的工资。

Worker 1 can do jobs 1,3,5 and he requires 1000 dollars. 
Worker 2 can do jobs 1,5 and he requires 2000 dollars. 
Worker 3 can do jobs 1,2 and he requires 1500 dollars. 
Worker 4 can do jobs 2,4 and he requires 2500 dollars. 
Worker 5 can do jobs 4,5 and he requires 1500 dollars. 
Worker 6 can do jobs 3,5 and he requires 1000 dollars. 

经过一点点计算和逻辑思考,我们可以得出结论,我们必须雇用工人 1,3,4 和 5,这意味着我们需要支付的最低工资是:1000+1500+2500+1500=5500 美元。

但是我们怎样才能找到一个有效的算法来输出这个数量呢?这不知何故让我想起了匈牙利算法,但是所有这些额外的限制让我无法应用它。

【问题讨论】:

  • 你真的需要解决这个问题吗?它看起来像一个家庭作业问题,并且您正在尝试执行复杂的优化。如果是这样,请以缓慢/简单的方式进行并提交。我怀疑这个讨论会很复杂和/或耗时。
  • @MooingDuck 这不是作业问题,这是过去的比赛问题。
  • “另外,如果我们雇佣工人 1 从事工作 1,那么我们希望他从事工作 2 和 5,因为我们已经支付了他的工资。”你不会为每份工作单独支付他的工资吗?还是说他会以 1000 美元的价格完成这三项工作?
  • @Yay295 他将以 1000 美元的价格完成所有三项工作,但我们不能以 333.33 美元的价格雇佣他只完成一项工作。为了更清楚,假设我们支付他每日工资。但在那一天,他做了各种各样的工作(当然,他能做的所有工作)。最后,我们希望完成所有工作。
  • N 和 K 可以有多大?

标签: algorithm optimization minimum hungarian-algorithm


【解决方案1】:

我们可以将所有工作的状态表示为三元系统中的一个数字(2-2 人剩余,1-1 人剩余,如果已经完成,则为 0)。现在我们可以计算 f(mask, k) = 在前 k 个中雇用一些工人的最小成本,使得剩余工作的状态为 mask。转换如下:我们要么转到 (mask, k + 1)(不雇用当前工人),要么转到 (new_mask, k + 1)(在这种情况下,我们向这个工人支付他的工资,让他做所有的他能做的工作)。答案是 f(0, K)。

时间复杂度为 O(3^N * K * N)。

这是一个如何进一步优化它的想法(并摆脱N 因素)。让我们假设当前的掩码是mask,这个人可以从另一个mask' 做工作。我们实际上可以简单地将mask 添加到mask',但是有一个问题:mask 中的2mask' 中的1 的位置会被破坏。但是我们可以修复:对于每个掩码,让我们预先计算一个二进制掩码allowed_mask,其中包含数字不是2 的所有位置。对于每个人和每个allowed_mask,我们可以预先计算mask' 的值。现在每个过渡都只是一个加法:

for i = 0 ... k - 1
    for mask = 0 ... 3^n - 1
        allowed_mask = precomputed_allowed_mask[mask]
        // make a transition to (i + 1, mask + add_for_allowed_mask[i][allowed_mask])
        // make a transition to (i + 1, mask)

请注意,只有 2^n 允许使用掩码。所以这个解决方案的时间复杂度是O(3^N * N + T * 2^N * K * N + T * 3^N * K)(第一项是为所有三元掩码预计算allowed_masks,第二项是为所有allowed_masks和人预计算mask',最后一项是dp本身)。

【讨论】:

  • 这个想法不错。但是你认为 O(3^NKN) 算法会在 1 秒(问题的时间限制)内执行,最大值为 N=8 和 K=60。我在解决旅行推销员问题时使用了面具。我使用位移来控制掩码,但这里会有点困难,因为我们使用的是三元系统。我考虑过创建一个特殊的函数,将数字转换为三进制(假设 10 代表掩码 00101)。对此有什么想法吗?
  • 另外我需要一个大小为 60x3^8(6561) 的二维数组,我需要更多时间来填充 INT_MAX 值。那么您认为这会有效地解决问题吗?
  • @Stefan4024 (3^8) * 60 * 8 = 3149280,这是一个非常小的数字。它应该可以在 1 秒内轻松运行(至少在 C++、Java 或其他具有类似性能的语言中)。
  • @Stefan4024 是的,使用特殊函数将数字从/转换为三进制看起来是一个不错的方法。
  • 当 K
猜你喜欢
  • 2015-09-02
  • 1970-01-01
  • 2013-05-18
  • 2010-11-16
  • 2011-05-03
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
相关资源
最近更新 更多