让我们说我们有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美元。
但是我们如何才能找到一个可以输出该数量的有效算法呢?这让我想起匈牙利算法,但所有这些额外的约束使我无法应用它。
答案 0 :(得分:2)
我们可以将所有工作的状态表示为三元系统中的数字(2个人剩余2个人,剩下1个人,如果已经完成则为0个人)。现在我们可以计算f(掩模,k)=在第一个k中雇佣一些工人的最小成本,使剩余工作的状态成为掩盖。过渡如下:我们要么去(掩码,k + 1)(不雇用当前的工人),要么去(new_mask,k + 1)(在这种情况下,我们向这个工人支付他的工资并让他做所有的工作他可以的工作)。答案是f(0,K)。
时间复杂度为O(3 ^ N * K * N)。
以下是如何进一步优化它(并摆脱N
因素)的想法。我们假设当前的掩码为mask
,并且该人可以从另一个mask'
开始工作。我们实际上只需将mask
添加到mask'
,但有一个问题:2
中的mask
和1
中mask'
的位置会破碎的。但我们可以修复:对于每个掩码,让我们预先计算包含数字不是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和people预先计算mask'
,最后一个用于dp本身)。