Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hungarian algorithm with multiple assignments

Let's say we're given N jobs and K workers to do those jobs. But for some jobs we need 2 employees, while for some we need just one. Also the employees can't do all jobs. For example worker 1 can do jobs 1,2 and 5, while not jobs 3 and 4. Also if we hire worker 1 to do job 1, then we want him to do jobs 2 and 5, since we've already paid him.

So for example let's say we have 5 jobs and 6 workers. For jobs 1,2 and 4 we need 2 men, while for jobs 3 and 5 we need just one. And here's the list of the jobs every worker can do and the wage he requires.

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. 

After little calculation and logical thinking we can conclude that we have to hire workers 1,3,4 and 5, which means that the minimum wage we need to pay is: 1000+1500+2500+1500=5500 dollars.

But how we can find an efficient algorithm that will output that amount? This somehow reminds me of the Hungarian Algorithm, but all those additional constrains makes it impossible for me to apply it.

like image 806
Stefan4024 Avatar asked Apr 09 '15 20:04

Stefan4024


1 Answers

We can represent a state of all jobs as a number in a ternary system(2-two people remaing, 1-one person remaining and 0 if it is already done). Now we can compute f(mask, k) = the smallest cost to hire some workers among the first k in such a way that the state of remaining jobs is mask. Transitions are as follows: we either go to (mask, k + 1)(not hiring the current worker) or we go to (new_mask, k + 1)(in this case we pay this worker his salary and let him do all the jobs he can). The answer is f(0, K).

The time complexity is O(3^N * K * N).

Here is an idea how to optimize it further(and get rid of the N factor). Let's assume that the current mask is mask and the man can do jobs from another mask'. We could actually simply add mask to mask', but there is one problem: the positions where there was 2 in the mask and 1 in mask' will get broken. But we can fix: for each mask, let's precompute a binary mask allowed_mask that contain all position where the digit is not 2. For each man and for each allowed_mask we can precompute that mask' value. Now each transition is just one addition:

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)

Note that there are only 2^n allowed masks. So the time complexity of this solution is O(3^N * N + T * 2^N * K * N + T * 3^N * K)(the first term is for precomputing allowed_masks for all ternary mask, the second one is for precomputing mask' for all allowed_masks and people, and the last is for dp itself).

like image 66
kraskevich Avatar answered Oct 06 '22 02:10

kraskevich