Emperor Arcana: 0/1 Knapsack & Coin Change
Tags: #◇CSALGCM #◇Problem Sets #◇HackerRank #◇Algorithms #◇Dynamic Programming
◇Overview
The Emperor Arcana represents dynamic programming foundations built on optimal substructure, state memoization, and space-optimized tabulation. This problem set explores two cornerstone problems: The 0/1 Knapsack Problem and The Fewest Coins Change Problem.
◇Problem 1: The Emperor's Vault (0/1 Knapsack)
Problem Description
Given imperial relics, each with an integer weight and integer value , and a royal vault cart with maximum carrying capacity . Determine the maximum total value of relics that can be transported. Each relic can be taken at most once ( or ).
Constraints:
Approach & Intuition: Optimal Substructure
Let be the maximum value achievable considering a subset of the first relics with maximum capacity limit .
For the -th relic with weight and value :
- Exclude relic : The capacity remains , giving value .
- Include relic (if ): Take relic , gaining value , while remaining capacity becomes , giving value .
Recurrence Relation
Stepped Calculation Trace
Consider :
- Relic 1:
- Relic 2:
- Relic 3:
- Relic 4:
Tabulation Matrix:
| Relic () | ||||||||
|---|---|---|---|---|---|---|---|---|
| 0 (Base) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 (1, 1) | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 2 (3, 4) | 0 | 1 | 1 | 4 | 5 | 5 | 5 | 5 |
| 3 (4, 5) | 0 | 1 | 1 | 4 | 5 | 6 | 6 | 9 |
| 4 (5, 7) | 0 | 1 | 1 | 4 | 5 | 7 | 8 | 9 |
Optimal Selection Traceback:
- At : Relic 4 not taken. Move to .
- At : Relic 3 is taken (). Remaining capacity . Move to .
- At : Relic 2 is taken (). Remaining capacity . Move to .
- Selected Relics: Relic 3 and Relic 2. Total Value: , Total Weight: .
Complexity Analysis
- Time Complexity: because each state in the grid is computed in time.
- Space Complexity:
- Standard 2D DP: .
- Optimized 1D DP: by traversing capacity backwards (), ensuring each item is considered at most once.
◇Problem 2: Imperial Coin Exchange (Coin Change Problem)
Problem Description
Given an array of coin denominations and a target amount . Find the minimum number of coins needed to make up that amount. If the amount cannot be formed, return . Each coin denomination has infinite supply (Unbounded).
Constraints:
Approach & Intuition
Let be the minimum number of coins to make amount .
For any target amount :
Base case: . Initialize all for .
Stepped Calculation Trace
Let and :
- (using coin 2)
- (using coin 5)
- (coins: ).
◇Complete C++ Implementation
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Problem 1: 0/1 Knapsack with 1D Space Optimization
int solveKnapsack01(int W, const vector<int>& weights, const vector<int>& values) {
int n = weights.size();
vector<int> dp(W + 1, 0);
for (int i = 0; i < n; i++) {
// Traverse backwards to prevent using the same item multiple times
for (int w = W; w >= weights[i]; w--) {
dp[w] = max(dp[w], dp[w - weights[i]] + values[i]);
}
}
return dp[W];
}
// Problem 2: Fewest Coins Change
int solveCoinChange(const vector<int>& coins, int amount) {
const int INF = 1e9;
vector<int> dp(amount + 1, INF);
dp[0] = 0;
for (int a = 1; a <= amount; a++) {
for (int coin : coins) {
if (a >= coin && dp[a - coin] != INF) {
dp[a] = min(dp[a], dp[a - coin] + 1);
}
}
}
return (dp[amount] >= INF) ? -1 : dp[amount];
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// Test 0/1 Knapsack
int W = 7;
vector<int> weights = {1, 3, 4, 5};
vector<int> values = {1, 4, 5, 7};
cout << "Max Knapsack Value: " << solveKnapsack01(W, weights, values) << "\n"; // Output: 9
// Test Coin Change
vector<int> coins = {1, 2, 5};
int amount = 11;
cout << "Min Coins Needed: " << solveCoinChange(coins, amount) << "\n"; // Output: 3
return 0;
}
◇References & Navigation
- Previous Topic: ◇Dynamic Programming Introduction
- Next Topic: ◇[PS] Hierophant Arcana
- Related Notes: ◇Towers Problem Set, ◇Divide and Conquer Introduction