Editorial for IOI '16 P4 - Paint by Numbers
Submitting an official solution before solving the problem yourself is a bannable offence.
Subtask 1 is as simple as it gets: just generate and intersect all possible locations of the clue.
Subtask 2: if you really have to, you can brute force the
Subtask 3 has a special case, helpfully shown in Example 2.
Except for that special case, we can only deduce black cells. This can be done greedily: for each clue, find the leftmost and the rightmost valid position of the corresponding block. If their intersection is non-empty, those cells are guaranteed to be black. (Proof of a more general statement is given below.)
The same approach works for subtask 4 as well. Additionally, we are able to deduce some white cells. One case is shown in Example 3. The same logic has to be applied at the beginning and at the end of a row. (In fact, the easiest solution is to prepend and append a white cell as a sentinel.)
Here's a tricky test case for subtask 4: ...._..._....
. Correct output: ?XX?_X_X_?XX?
. The tricky part here is that we can deduce the white cell at index
Subtask 4 was as far as we could get with an easy greedy approach. In order to solve the general version, we will use dynamic programming.
One possible solution looks as follows:
- Step 1: Compute prefix sums of given white cells and given black cells (each separately).
- Step 2: For each
and , compute the answer to the following question: "Is there a valid solution if we only consider the first clues and the first cells of the given puzzle (as if cutting away and discarding the rest)?" - Base case of the recurrence: If
, this is possible iff there is no given black cell among the first cells. - Recursive case: If cell
is forced white, . If cell is forced black, we verify that it is possible to place the last block there (the number of forced white cells it overlaps must be zero, the next cell to the left must be able to be white) and if that is the case, we make a recursive call where was the corresponding clue. Finally, if cell isn't forced, the answer is the logical or of both above cases. - Step 3: The same in reverse, i.e., with suffixes of the puzzle and the list of clues.
- Step 4: For each cell, we verify whether it can be white. A cell cannot be white if it is forced to be black. If that is not the case, we try all possibilities for the number of black blocks to the left of the cell, and verify each possibility using the data we precomputed in steps 2+3.
- Step 5: For each clue, we mark all the cells where it can be located as cells that can be black. Suppose we are processing clue
and that its value is . For each , we verify whether the clued block can be placed starting from cell . This requires a few checks that can all be done in constant time:- cells
and must not be forced black - cells
through must not be forced white - there must be a valid solution for the first
clues and the first cells - there must be a valid solution for the last
clues and the last cells
- cells
The above solution can conveniently be implemented in
Proof of the greedy solution (subtasks 1-4)
Theorem 1. Consider the version of our puzzle where initially each cell is either unknown or forced white.
Suppose that there is a cell
Proof. Suppose that we have
We will now construct a new solution as follows: take the first
This is a valid solution because in the second solution, the first
Comments