cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 127 of 218
Ideas this builds on
Extra state & 3D DP127 / 218

Logical dimensions are not storage dimensions

Picture

A DP can ask a two-coordinate question while storing one row of answers. This is safe only when overwritten answers will never be needed again. Space compression is about the lifetime of dependencies, not deleting information from the mathematical problem.

Predict

You have one item of weight 2 and value 3, capacity 4, and update a single knapsack row in increasing capacity order. What wrong answer can appear?

Reveal the reasoning

At capacity 2, you write 3. At capacity 4, you read that newly written 3 and add the same item again, yielding 6. The update accidentally changed “use once” into reuse.

Go deeper: identify which layer each read belongs to

Before each item, dp[c] represents the best value with only earlier items. For 0/1 knapsack, descending capacity ensures dp[c-weight] still belongs to that earlier layer when read.

def pack_compressed(items, capacity):
    dp = [0] * (capacity + 1)
    for weight, value in items:
        for room in range(capacity, weight - 1, -1):
            dp[room] = max(dp[room], value + dp[room - weight])
    return dp[capacity]

assert pack_compressed([(2, 3)], 4) == 3
assert pack_compressed([(2, 3), (3, 4), (4, 5)], 5) == 7

The logical state remains (number_of_items_considered, capacity). Time stays O(nW); storage falls to O(W). Unlimited reuse often uses increasing capacity because reading the current item layer is intentional. Loop direction follows which dependency version you need.

For right/down grid counts, a forward row scan can read the old value in the current column as “from above,” and the newly updated previous column as “from left.” For two robots, the next row’s C×C layer can suffice, reducing storage to O(C²) if you allocate or safely reset a separate current layer.

Python trap: [[0] * cols] * rows creates several references to one row. Use a comprehension to create independent rows. Similarly, memoizing a function that reads an actively changing grid can reuse stale answers.

Reconstruction is a trade-off: discarding layers can remove information needed to recover the actual chosen path or items. You may retain parent decisions or recompute selected information.

Analogy limit: a compact implementation is not automatically a simpler explanation. Derive the full state first; compress only after dependency lifetimes are clear.

Change one rule

A recurrence reads an entry two layers back as well as the previous layer. Is keeping only one previous layer always sufficient?

Check the variation

No. Preserve all values needed by future transitions, perhaps with two previous layers or another proved summary. Count dependencies, not the number of loops in the code.

Connect

Coin change shows loop order encoding a different counting meaning. String DP needs careful diagonal preservation. Interval DP has dependencies spanning many interval lengths, so rolling rows require a separate argument.