JOIN
 Match Editorial
2003 TopCoder Collegiate Challenge
Round 1 - International

Saturday, February 22, 2003

Summary

The most notable aspect of this round was the Level 2 problem, which was solved by only four coders. This lead to a lot of successful challenges by coders such as John Dethridge. The The Level 1 and Level 3 problems had very high success rates among those that submitted the problems, but only 14 coders managed to submit a possible solution for the Level 3 problem.

# The Problems

Pareto
Used as: Level 1 :
 Value 250 Submission Rate 84 / 102 (82.35%) Success Rate 78 / 84 (92.86%) High Score lars for 232.90 points

#### Implementation

This problem can be solved by iterating over all pairs of outcomes. For each pair of outcomes A and B, one of the following will be true: A may be suboptimal to B; B may be suboptimal to A; or neither may be suboptimal to the other. In the first two cases, we can eliminate one of the outcomes as a candidate for being a Pareto optimum.

We can do this with two nested loops. The outer loop iterates over all outcomes. The inner loop also iterates over all outcomes. If the outer outcome is not suboptimal to any of the inner outcomes, we know that it is a Pareto optimum and increase a counter. We return this counter after iterating over all pairs in this fashion.

Coherence
Used as: Level 2 :
 Value 500 Submission Rate 59 / 102 (57.84%) Success Rate 4 / 59 (6.78%) High Score haha for 406.84 points

#### Implementation

Very few people were able to get this problem, yet the solution is almost embarrassingly simple. The first step should be to compare the number of foreground pixels to the number of background pixels. We will get very bogus results if there are more foreground pixels than background pixels, and it is this sort of test case that broke a great many submissions. The simple fix is to simply invert the colors if there are more foreground pixels than background pixels. This can be as simple as n <?= w * h - n in C++.

There are three possible ways to optimally layout the pixels. The first is to fill rows in the image with the foreground color, until there are not enough pixels left to fill a row (in which case you fill as much of the row as possible, aligned to the left). The second is to fill columns in the exact same fashion. The third is to fill in a rectangle that shares two sides with adjacent borders of the image (i.e., a corner).

For each of the first two methods, there is only one optimal count. The number of boundaries will be the width (height) of the image, plus an additional boundary if we have an incompletely filled row (column). For the third method, we need to iterate through all possible rectangle sizes. For each rectangle, the number of boundaries will be at least the height of the rectangle plus its width. This is true even for rectangles that cannot be completely filled. Only rectangles where every column (row) except for one is filled will be optimal, and in such cases the boundary count works out the same as for the fully filled rectangle; for each pixel that is removed, two previously unexposed boundaries become exposed, while two previously exposed boundaries become internal to the background.

So to solve the problem, we compute the number of boundaries that we would get if we fill in each of the first two fashions, and remember only the minimum. Then we iterate through every possible rectangle size that would fit in the image and be large enough to hold the number of pixels we need, and remember the minimum between our previous minimum and the sum of the dimensions of the rectangle. After all this we return the minimum value.

Wireless
Used as: Level 2 :
 Value 1000 Submission Rate 14 / 102 (13.72%) Success Rate 12 / 14 (85.71%) High Score John Dethridge for 837.02 points

#### Implementation

We start out with a 2048-element boolean array (initialized all to false) to indicate whether any particular angle is protected. Next we need to define a function that translates an angle name (e.g. "NENE") to an index into this array.

One way to do this is to precompute all the mappings between angle names and indices. To do this we will define a function that takes an angle name, its index, the index of its nearest neighbors of the same name length, and recursively generates the indices for all angles that have that name as a suffix in their own names. We would call this function four times at the top level, once for each cardinal direction. For instance, to generate all angle names that end with "N", we will start with name = "N", id = 512, prev = 0, and next = 1024. In the definition of this function, we simply determine the two characters that we can add to the beginning of the angle name to make new valid angles and recurse on these new angles. The two characters can be determined by looking at the index. Indices in the range 1-511 can be modified by either N (an increase in angle) or E (a decrease). Indices in the range 513-1023 are modified by either W (increase) or N (decrease). Indices in the range 1025-1535 are modified by either S (increase) or W (decrease). And indices in the range 1537-2047 are modified by either E (increase) or S (decrease). The indices of 0, 512, 1024, and 1536 -- corresponding to the four cardinal directions -- have their own modifiers, which are easy to determine. We will need a two-way mapping for returning the angle name when we're done.

Once we've generated a mapping of angle name to index, the rest of the problem is easy. For each wall description, we iterate from the index of the first angle to the index of the second angle (being careful to wrap around properly when necessary) and mark the angles covered by this range as protected (both endpoints being included). Once we have done this for all walls, we then find the smallest index that is unprotected, and then return the name associated with that index.

By Logan
TopCoder Member