Intuition
I'll try. The naive approach is to list all possible solutions and choose the best. With this in mind, looking for rooms k that can accommodate meetings n is equivalent to looking for a section k -way n . Section example 2 -way << 25>: [ 0,2,4 ] and [ 1,3 ] in the OP example:
|---0------| |---------4---------| |------1-----| |----------3-----------| |--------2-------|
Thus, the main idea is to list all k level sections of meetings n with the restriction that two overlapping meetings cannot belong to the same cluster. For example, [ 0,1,2 ] and [ 3,4 ] not a valid section because meetings [ 0,1,2 ] cannot be performed in a room; the same goes for meetings [ 3,4 ] . Fortunately, the restriction is easy to implement using a recursive approach.
Algorithm
With Python it looks like this:
def kWay( A, k, overlap ) : """ A = list of meeting IDs, k = number of rooms, overlap[ meeting ID m ] = set of meetings overlapping with m """ if k == 1 :
It looks a bit more complicated, but it's actually quite simple when you realize that this is just a recursive algorithm for k ways of partitioning + 2 extra lines to ensure that we only consider valid sections.
Solution Example OP
Now let's prepare the input using the OP example:
import collections n = 5 k = 2
Now we just iterate over the valid 2 -way sections and print the dimensions of the room. There is only one valid section, so this is our solution:
for partition in kWay( A, k, overlap ) : print partition, [ max( size[x] for x in c ) for c in partition ] [[3, 1], [4, 2, 0]] [10, 10]
So, meetings 1,3 go to a room of size 10 , and meetings 0,2,4 go to a room of size 10 .
A slightly more complex example
But there was only one valid 2 -way section, so of course it was also the optimal solution. How boring! Add a new meeting 5 and a new room for the OP example, to make it more interesting:
|---0------| |---5---| |---------4---------| |------1-----| |----------3-----------| |--------2-------|
Relevant input data:
n = 6 k = 3
And the result:
for partition in kWay( A, k, overlap ) : print partition, [ max( size[x] for x in c ) for c in partition ] [[3, 1], [4, 2, 0], [5]] [10, 10, 2] [[3, 1], [4, 2], [5, 0]] [10, 8, 10] [[3, 0], [4, 2], [5, 1]] [10, 8, 8] [[3], [4, 2, 0], [5, 1]] [10, 10, 8] [[4, 5, 1], [3, 0], [2]] [8, 10, 6] [[4, 5, 1], [3], [2, 0]] [8, 10, 10] [[4, 5, 0], [3, 1], [2]] [10, 10, 6] [[4, 5], [3, 1], [2, 0]] [8, 10, 10]
The optimal 3 -way section is [[3, 1], [4, 2, 0], [5]] , and the optimal room sizes are [10, 10, 2] . You can also get the minimum size of all rooms directly:
min( sum( [ max( size[x] for x in c ) for c in partition ] ) for partition in kWay( A, k, overlap ) ) 22