UVa 10003 - Cutting Sticks

10003 - Cutting Sticks

 * http://acm.uva.es/p/v100/10003.html

Summary
This is a straightforward Dynamic Programming problem. The trick is to define the recurrence carefully.

Explanation
Since $$n$$ can be as large as 50, trying every ordering of cuts is well beyond feasible.

The concept behind the recurrence involves rephrasing it so that it can be answered with subproblems.

Given a series of locations to make the cuts and its borders, what is the cheapest way to make all the cuts? The answer is basically try everything and take the minimum - make a cut everywhere, and try to answer that subproblem that comes up.

So the function $$C( a_1, a_2, \ldots, a_n )$$ where $$a_i$$ are places where cuts are possible. In particular, $$a_1$$ and $$a_n$$ will serve as the end points, since it never makes sense to make a cut at an edge (and thus having the same problem).

When we make a cut at $$a_i$$, it gives us two subproblems - the left side, and the right side. With the base case $$C( a_i, a_{i+1} ) = 0$$ (which basically means if there is one board with no more cuts to be made, the cost is zero), we can now formulate the recurrence:

$$C(a_i, a_j) = \min_{k \in (i+1, \ldots, j-1)} \left[ C(a_i, a_k) + C(a_k, a_j) \right]+cost(a_i,a_j)$$

The cost of making a cut is simply:

$$cost( a_i, a_j ) = a_j - a_i $$

Gotchas
The test input is huge on this program, so even being as efficient as possible you're going to have a hard time getting this one in under the time limit. I recommend allocating all of your arrays up front, and only clearing out their memory as necessary for test cases. It wasn't until I did this did I get this solution to run in time, and it still took a whopping 2.64 seconds.

Input
100 3 25 50 75 10 4 4 5 7 8 0

Output
The minimum cutting is 200. The minimum cutting is 22.