Editorial for Mock CCC '15 S4 - Ice Pillars
Submitting an official solution before solving the problem yourself is a bannable offence.
Approach 1 — Brute Force
Generate all permutations in which to break the blocks. Simulate the chain reactions when they occur.
This is enough to obtain
Time Complexity:
Approach 2 — Divide and Conquer
A faster solution uses memoization on a divide and conquer principle. The subproblem is determining the cost to knock down every pillar in the range
- In the base case,
, and there is only 1 pillar to consider. The cost to knock it down is just its durability minus the possible damages done by the pillars to its left and right. - Otherwise, if there is more than 1 pillar to consider:
- If pillar
is broken and completely knocks over pillar without you having to do any work, then we can narrow the range by 1 from the left and mark the newest left outside-border pillar as broken. - If pillar
is broken and completely knocks over pillar without you having to do any work, then we can narrow the range by 1 from the right and mark the newest right outside-border pillar as broken. - Otherwise, we test every pillar between
and as the first pillar to knock down, taking into account collateral damage. The total cost is the cost to break down this pillar, plus the cost to break all the pillars to the left of it, plus the cost to break all of the pillars to the right of it. In other words, we divide the range in half and let recursion handle each side. The minimum cost across all these tests is the answer.
- If pillar
If we cache the results every time we compute them, we only have
Time Complexity:
Approach 3 — Dynamic Programming
To get full marks, we abandon recursion altogether and go for pure dynamic programming. This problem displays optimal substructure in the following way. Consider the base case where we only want to break only the first (leftmost) block. Given this value, we can then use it to calculate the cost of breaking the two leftmost pillars. Likewise, if we know the cost to break the first
There are 2 values in our state: the current pillar we are on, and whether it is broken (either
- the pillar before it is already knocked down (i.e.
): Here, the additional cost to knock down one more pillar (the current one) is just the current pillar's durability , minus the damage done by the previous pillar . - the pillar before it is not knocked down (i.e.
): Here, there is no collateral damage at all, so the extra cost to break one more pillar (the current one) is just its durability .
Calculating
- the pillar before it is already knocked down (i.e.
): Here, the additional cost to knock down one more pillar (the current one) is just the current pillar's durability , minus the damage done by the previous pillar , minus the damage done by the next pillar . - the pillar before it is not knocked down (i.e.
): Here, there is no collateral damage at all from the previous pillar, so the extra cost to break one more pillar (the current one) is just its durability minus the damage done by the next pillar .
Time Complexity:
Comments