{
  "id": "greedy-dp/dynamic-programming",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/greedy-dp/dynamic-programming",
  "topic": {
    "slug": "greedy-dp",
    "title": "Greedy & DP"
  },
  "title": "Dynamic Programming",
  "tagline": "Solve each small problem once, write the answer down, and never solve it again.",
  "vizKind": "grid",
  "complexity": {
    "time": {
      "best": "O(n·k)",
      "average": "O(n·k)",
      "worst": "O(n·k)"
    },
    "space": "O(n)",
    "growth": "linear",
    "note": "One cell per amount (n), touched once per coin (k). The naive recursion is exponential — it explores the same subproblems again and again. Filling a table turns a problem that would take longer than the universe has existed into one that finishes instantly."
  },
  "code": {
    "javascript": "// Fewest coins that add up to `amount`.\nfunction coinChange(coins, amount) {\n  const dp = Array(amount + 1).fill(Infinity);\n  dp[0] = 0;                     // 0 coins make 0\n\n  for (const coin of coins) {\n    for (let a = coin; a <= amount; a++) {\n      // either the best we already had...\n      // ...or one `coin` plus the best for (a - coin)\n      dp[a] = Math.min(dp[a], dp[a - coin] + 1);\n    }\n  }\n\n  return dp[amount] === Infinity ? -1 : dp[amount];\n}",
    "python": "# Fewest coins that add up to `amount`.\ndef coin_change(coins, amount):\n    dp = [float('inf')] * (amount + 1)\n    dp[0] = 0                      # 0 coins make 0\n\n    for coin in coins:\n        for a in range(coin, amount + 1):\n            # either the best we already had...\n            # ...or one coin plus the best for (a - coin)\n            dp[a] = min(dp[a], dp[a - coin] + 1)\n\n\n    return -1 if dp[amount] == float('inf') else dp[amount]\n",
    "java": "// Fewest coins that add up to `amount`.\nint coinChange(int[] coins, int amount) {\n  int[] dp = new int[amount + 1];\n  Arrays.fill(dp, Integer.MAX_VALUE);\n  dp[0] = 0;                     // 0 coins make 0\n\n  for (int coin : coins) {\n    for (int a = coin; a <= amount; a++) {\n      if (dp[a - coin] != Integer.MAX_VALUE) {\n        dp[a] = Math.min(dp[a], dp[a - coin] + 1);\n      }\n    }\n  }\n\n  return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];\n}",
    "cpp": "// Fewest coins that add up to `amount`.\nint coinChange(vector<int>& coins, int amount) {\n  const int INF = 1e9;\n  vector<int> dp(amount + 1, INF);\n  dp[0] = 0;                     // 0 coins make 0\n\n  for (int coin : coins) {\n    for (int a = coin; a <= amount; a++) {\n      // one coin plus the best for (a - coin)\n      dp[a] = min(dp[a], dp[a - coin] + 1);\n    }\n  }\n\n  return dp[amount] >= INF ? -1 : dp[amount];\n}"
  },
  "defaultInput": [
    6
  ],
  "defaultTarget": null,
  "inputHint": "Type a target amount from 1 to 12. Coins available: 1, 3 and 4.",
  "pitfalls": [
    {
      "wrong": "Reaching for DP on any problem that looks hard.",
      "right": "DP needs two specific things: the same subproblems must come up more than once (overlapping subproblems), and the big answer must be buildable from small ones (optimal substructure). No overlap, no benefit."
    },
    {
      "wrong": "Getting the base case wrong.",
      "right": "dp[0] = 0 — zero coins make zero. Everything else builds on that one free answer. A wrong base case quietly poisons the whole table."
    },
    {
      "wrong": "Forgetting that some amounts may be impossible.",
      "right": "Start every cell at infinity, meaning 'no way known'. If it's still infinite at the end, no combination of coins makes that amount — and you must return −1, not infinity."
    },
    {
      "wrong": "Thinking greedy works here.",
      "right": "Always taking the biggest coin fails: with coins 1, 3, 4 and a target of 6, greedy takes 4 then 1 then 1 — three coins. The real answer is 3+3, just two. Greedy is not DP."
    }
  ],
  "quiz": [
    {
      "q": "What two properties must a problem have for DP to help?",
      "options": [
        "It must be sorted and unique",
        "Overlapping subproblems, and optimal substructure",
        "It must be recursive and small",
        "It must involve a graph"
      ],
      "answer": 1,
      "why": "The same subproblems must recur (so caching them pays off), and the big answer must be buildable from smaller answers. Miss either and DP buys you nothing."
    },
    {
      "q": "Coins are 1, 3 and 4. What's the fewest that make 6?",
      "options": [
        "2 (3 + 3)",
        "3 (4 + 1 + 1)",
        "6 (1 six times)",
        "It's impossible"
      ],
      "answer": 0,
      "why": "3 + 3 = 6, using two coins. Greedy would grab the 4 first and end up needing three coins — which is exactly why greedy fails here and DP doesn't."
    },
    {
      "q": "Why is the naive recursion for coin change so slow?",
      "options": [
        "Recursion is always slow",
        "It solves the same subproblems over and over, exponentially many times",
        "It uses too much memory",
        "It has to sort the coins first"
      ],
      "answer": 1,
      "why": "Different branches keep arriving at the same amount and recompute it from scratch. DP writes each answer down once, collapsing exponential work into a single pass over a table."
    }
  ],
  "problems": [
    {
      "name": "Climbing Stairs",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/climbing-stairs/"
    },
    {
      "name": "Coin Change",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/coin-change/"
    },
    {
      "name": "House Robber",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/house-robber/"
    },
    {
      "name": "Longest Common Subsequence",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/longest-common-subsequence/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 30,
    "frames": [
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "coins 1, 3, 4 — fewest needed to make each amount"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "coins": "1 3 4",
          "target": 6
        },
        "explanation": "How few coins from {1, 3, 4} add up to 6? Build a table: one cell per amount from 0 up to 6. Amount 0 needs 0 coins — that's the one answer we get for free.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "sorted"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "now allowed to use the 1 coin"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 6,
        "variables": {
          "coin": 1
        },
        "explanation": "Now let the 1-coin into the mix, and sweep every amount from 1 upward.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "pivot"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": true
              },
              {
                "value": "∞",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "1 = 1 + 0"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 1,
          "coin": 1,
          "best_for": "0 → 0",
          "candidate": "1",
          "current": "∞"
        },
        "explanation": "To make 1, use one 1 coin plus the best way to make 0, which took 0. That's 0 + 1 = 1 coins. Better than the ∞ we had.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "1 now takes 1 coin"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 1,
          "best": 1
        },
        "explanation": "Write 1 into cell 1. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 1,
          "swaps": 1
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "∞",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "2 = 1 + 1"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 2,
          "coin": 1,
          "best_for": "1 → 1",
          "candidate": "2",
          "current": "∞"
        },
        "explanation": "To make 2, use one 1 coin plus the best way to make 1, which took 1. That's 1 + 1 = 2 coins. Better than the ∞ we had.",
        "stats": {
          "comparisons": 2,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "2",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "2 now takes 2 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 2,
          "best": 2
        },
        "explanation": "Write 2 into cell 2. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 2,
          "swaps": 2
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": true
              },
              {
                "value": "∞",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "3 = 1 + 2"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 3,
          "coin": 1,
          "best_for": "2 → 2",
          "candidate": "3",
          "current": "∞"
        },
        "explanation": "To make 3, use one 1 coin plus the best way to make 2, which took 2. That's 2 + 1 = 3 coins. Better than the ∞ we had.",
        "stats": {
          "comparisons": 3,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": true
              },
              {
                "value": "3",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "3 now takes 3 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 3,
          "best": 3
        },
        "explanation": "Write 3 into cell 3. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 3,
          "swaps": 3
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": true
              },
              {
                "value": "∞",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "4 = 1 + 3"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 4,
          "coin": 1,
          "best_for": "3 → 3",
          "candidate": "4",
          "current": "∞"
        },
        "explanation": "To make 4, use one 1 coin plus the best way to make 3, which took 3. That's 3 + 1 = 4 coins. Better than the ∞ we had.",
        "stats": {
          "comparisons": 4,
          "swaps": 3
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": true
              },
              {
                "value": "4",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "4 now takes 4 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 4,
          "best": 4
        },
        "explanation": "Write 4 into cell 4. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 4,
          "swaps": 4
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "4",
                "role": "sorted",
                "source": true
              },
              {
                "value": "∞",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "5 = 1 + 4"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 5,
          "coin": 1,
          "best_for": "4 → 4",
          "candidate": "5",
          "current": "∞"
        },
        "explanation": "To make 5, use one 1 coin plus the best way to make 4, which took 4. That's 4 + 1 = 5 coins. Better than the ∞ we had.",
        "stats": {
          "comparisons": 5,
          "swaps": 4
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "4",
                "role": "sorted",
                "source": true
              },
              {
                "value": "5",
                "role": "active",
                "source": false
              },
              {
                "value": "∞",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "5 now takes 5 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 5,
          "best": 5
        },
        "explanation": "Write 5 into cell 5. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 5,
          "swaps": 5
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "4",
                "role": "sorted",
                "source": false
              },
              {
                "value": "5",
                "role": "sorted",
                "source": true
              },
              {
                "value": "∞",
                "role": "active",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "6 = 1 + 5"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 6,
          "coin": 1,
          "best_for": "5 → 5",
          "candidate": "6",
          "current": "∞"
        },
        "explanation": "To make 6, use one 1 coin plus the best way to make 5, which took 5. That's 5 + 1 = 6 coins. Better than the ∞ we had.",
        "stats": {
          "comparisons": 6,
          "swaps": 5
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "4",
                "role": "sorted",
                "source": false
              },
              {
                "value": "5",
                "role": "sorted",
                "source": true
              },
              {
                "value": "6",
                "role": "active",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "6 now takes 6 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 6,
          "best": 6
        },
        "explanation": "Write 6 into cell 6. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 6,
          "swaps": 6
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "4",
                "role": "sorted",
                "source": false
              },
              {
                "value": "5",
                "role": "sorted",
                "source": false
              },
              {
                "value": "6",
                "role": "sorted",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "now allowed to use the 3 coin"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 6,
        "variables": {
          "coin": 3
        },
        "explanation": "Now let the 3-coin into the mix, and sweep every amount from 3 upward.",
        "stats": {
          "comparisons": 6,
          "swaps": 6
        },
        "accent": "pivot"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "active",
                "source": false
              },
              {
                "value": "4",
                "role": "sorted",
                "source": false
              },
              {
                "value": "5",
                "role": "sorted",
                "source": false
              },
              {
                "value": "6",
                "role": "sorted",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "3 = 3 + 0"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 3,
          "coin": 3,
          "best_for": "0 → 0",
          "candidate": "1",
          "current": "3"
        },
        "explanation": "To make 3, use one 3 coin plus the best way to make 0, which took 0. That's 0 + 1 = 1 coins. Better than the 3 we had.",
        "stats": {
          "comparisons": 7,
          "swaps": 6
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "active",
                "source": false
              },
              {
                "value": "4",
                "role": "sorted",
                "source": false
              },
              {
                "value": "5",
                "role": "sorted",
                "source": false
              },
              {
                "value": "6",
                "role": "found",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "3 now takes 1 coin"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 3,
          "best": 1
        },
        "explanation": "Write 1 into cell 3. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 7,
          "swaps": 7
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "4",
                "role": "active",
                "source": false
              },
              {
                "value": "5",
                "role": "sorted",
                "source": false
              },
              {
                "value": "6",
                "role": "sorted",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "4 = 3 + 1"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 4,
          "coin": 3,
          "best_for": "1 → 1",
          "candidate": "2",
          "current": "4"
        },
        "explanation": "To make 4, use one 3 coin plus the best way to make 1, which took 1. That's 1 + 1 = 2 coins. Better than the 4 we had.",
        "stats": {
          "comparisons": 8,
          "swaps": 7
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "active",
                "source": false
              },
              {
                "value": "5",
                "role": "sorted",
                "source": false
              },
              {
                "value": "6",
                "role": "found",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "4 now takes 2 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 4,
          "best": 2
        },
        "explanation": "Write 2 into cell 4. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 8,
          "swaps": 8
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "5",
                "role": "active",
                "source": false
              },
              {
                "value": "6",
                "role": "sorted",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "5 = 3 + 2"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 5,
          "coin": 3,
          "best_for": "2 → 2",
          "candidate": "3",
          "current": "5"
        },
        "explanation": "To make 5, use one 3 coin plus the best way to make 2, which took 2. That's 2 + 1 = 3 coins. Better than the 5 we had.",
        "stats": {
          "comparisons": 9,
          "swaps": 8
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "active",
                "source": false
              },
              {
                "value": "6",
                "role": "found",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "5 now takes 3 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 5,
          "best": 3
        },
        "explanation": "Write 3 into cell 5. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 9,
          "swaps": 9
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "6",
                "role": "active",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "6 = 3 + 3"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 6,
          "coin": 3,
          "best_for": "3 → 1",
          "candidate": "2",
          "current": "6"
        },
        "explanation": "To make 6, use one 3 coin plus the best way to make 3, which took 1. That's 1 + 1 = 2 coins. Better than the 6 we had.",
        "stats": {
          "comparisons": 10,
          "swaps": 9
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "active",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "6 now takes 2 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 6,
          "best": 2
        },
        "explanation": "Write 2 into cell 6. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 10,
          "swaps": 10
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "now allowed to use the 4 coin"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 6,
        "variables": {
          "coin": 4
        },
        "explanation": "Now let the 4-coin into the mix, and sweep every amount from 4 upward.",
        "stats": {
          "comparisons": 10,
          "swaps": 10
        },
        "accent": "pivot"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "active",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "4 = 4 + 0"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 4,
          "coin": 4,
          "best_for": "0 → 0",
          "candidate": "1",
          "current": "2"
        },
        "explanation": "To make 4, use one 4 coin plus the best way to make 0, which took 0. That's 0 + 1 = 1 coins. Better than the 2 we had.",
        "stats": {
          "comparisons": 11,
          "swaps": 10
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "active",
                "source": false
              },
              {
                "value": "3",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "found",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "4 now takes 1 coin"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 4,
          "best": 1
        },
        "explanation": "Write 1 into cell 4. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 11,
          "swaps": 11
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "3",
                "role": "active",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "5 = 4 + 1"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 5,
          "coin": 4,
          "best_for": "1 → 1",
          "candidate": "2",
          "current": "3"
        },
        "explanation": "To make 5, use one 4 coin plus the best way to make 1, which took 1. That's 1 + 1 = 2 coins. Better than the 3 we had.",
        "stats": {
          "comparisons": 12,
          "swaps": 11
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": true
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "active",
                "source": false
              },
              {
                "value": "2",
                "role": "found",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "5 now takes 2 coins"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 5,
          "best": 2
        },
        "explanation": "Write 2 into cell 5. Notice we never recomputed anything — we reached back to an answer we already had.",
        "stats": {
          "comparisons": 12,
          "swaps": 12
        },
        "accent": "found"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": true
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "active",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "6 = 4 + 2"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 10,
        "variables": {
          "amount": 6,
          "coin": 4,
          "best_for": "2 → 2",
          "candidate": "3",
          "current": "2"
        },
        "explanation": "To make 6, use one 4 coin plus the best way to make 2, which took 2. That's 2 + 1 = 3 coins. Not better than the 2 we had.",
        "stats": {
          "comparisons": 13,
          "swaps": 12
        },
        "accent": "compare"
      },
      {
        "data": {
          "cells": [
            [
              {
                "value": "0",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "1",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "sorted",
                "source": false
              },
              {
                "value": "2",
                "role": "found",
                "source": false
              }
            ]
          ],
          "rowLabels": [
            "coins"
          ],
          "colLabels": [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "caption": "answer: 2 coins make 6"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 14,
        "variables": {
          "amount": 6,
          "coins_needed": "2",
          "cellsFilled": 7
        },
        "explanation": "6 takes just 2 coins. We filled 7 cells, each once. The naive recursion would have explored the same subproblems over and over — this is the difference dynamic programming makes.",
        "stats": {
          "comparisons": 13,
          "swaps": 12
        },
        "accent": "found"
      }
    ]
  }
}