Tuesday, May 12, 2015

FairWorkload

Determine the minimum time needed to search through a set of folders given a number of workers.
The workers must search a contiguous set of folders, and each folder may take a varying amount
of time to process.

FairWorkload is a problem that begs for a dynamic programming solution. To solve this, we'll build up a table
that holds the best finishing time we can achieve given a number of workers and a number of folders. We'll
start with the trivial case of just one worker. Using that information, we'll add additional workers and
folders until we've completed the table. The result will be the table shown below. With that, we can just
return the value of the cell in the bottom right corner.

Don't be confused by the number of workers; I've labeled the table using its indexes, so "Workers 0" is the
case with one worker. Same goes for folders across the top.

The table is initialized by filling in the top row. With just one worker, the number of sections searched
is just the sum of the sections in all previous folders, plus the number of sections in the current folder.
This could have been done more efficiently by keeping a running total of the number of sections, but since I
needed a sumSections() method anyway, I chose to rely on that here.

Note that we cannot satisfy the constraints of the problem if there are fewer folders than their are workers.
These cases are noted with a -1, although that never really comes into play.

Things begin to get interesting with the second worker. With 2 workers and 2 folders, we know that 1 worker
must look through 10 sections to complete 1 folder, and that worker 2 must look through 20 sections to complete
the next folder. Therefore the minimum number of sections is 20.

With 2 workers and three folders we have a choice in how to complete the task. We can either assign the
first 2 folders to worker 1, and the third to worker 2 (scenario 1)- or we can assign just the first folder to
worker 1, and the remaining two to worker 2 (scenario 2). We need to check both cases and see with gives the
better result. Scenario 1 gives 10 + 20 = 30 sections to worker 1 and 30 sections to worker 2. Scenario 2
gives 10 sections to worker 1 and 20 + 30 = 50 sections to worker 2. The max of 30 in scenario 1 is better
than the max of 50 in scenario 2, so 30 is our value here.

The loop on line 39 works through each scenario. In general, we want to minimize the maximum value of sections
as we move the dividing line across the range of folders. The dividing line separates the work done by
previous workers on one side (which can be pulled right out of the table), and the work done by the latest
worker, which is the sum of the number of sections remaining.

Folder / Number of Sections

0/10

1/20

2/30

3/40

4/50

5/60

6/70

7/80

8/90

Workers0

10

30

60

100

150

210

280

360

450

1

-1

20

30

60

90

110

150

210

240

2

-1

-1

30

40

60

90

110

150

170

3

-1

-1

-1

40

50

60

90

110

150

4

-1

-1

-1

-1

50

60

70

90

110

This is a great problem to hone you dynamic programming skills. Please take the time to make sure that you
understand what's going on. It's a great tool to have for many TopCoder problems.

To help make it as clear as I can, let me walk through the final cell. Imagine that the bottom right cell
was not yet filled in. From the previous row, we know the best solutions for each number of folders with one
less worker. Since each worker must have at least one folder, we can divide the 9 folders up as follows:

Folders 0 - 4 processed by workers 0 - 3 / Folders 5 - 8 processed by Worker 4. Again from the table, the
previous workers can do folders 0 - 4 with a max of 50. Worker 4 has 60 + 70 + 80 + 90 = 300 sections. Better
than before, but still not the best we can do.

It turns out the best solution is to have Folders 0 - 7 processed by workers 0 - 3 / and just Folder 8 processed
by worker 4. The previous workers have a max of 110 sections, and Worker 4 has just 90 sections. The
max of 110 is the best we can do, so that's what goes into the bottom right cell.

Thank you for taking the time to read this solution. I welcome
any feedback you may have.