Computer Science / Dynamic Programming & 0/1 Knapsack
FREE TO EXPLORE
LABORATORY 11 · COMPUTER SCIENCE

Dynamic Programming & 0/1 Knapsack lab report

A worked dynamic programming & 0/1 knapsack lab report with benchmark data tables, asymptotic graphs, calculations, uncertainty and conclusions.

WORKED EXAMPLE · BENCHMARK OBSERVATIONS

A complete example laboratory report.

Simulated demonstration data.

This report illustrates formal algorithmic benchmarking, operation counting arithmetic, and regression analysis. Replace its observations with your own benchmark telemetry when preparing a practical submission.

Student: __________________Student ID: __________________Course: __________________Date: __________________Partner: __________________Instructor: __________________

1. Title and aim

Empirical Analysis of Dynamic Programming: Memoization vs. Tabulation, Optimal Substructure, Overlapping Subproblems, and 0/1 Knapsack State Space Complexity. To investigate the fundamental mechanisms of Dynamic Programming (Optimal Substructure and Overlapping Subproblems), quantitatively contrast Top-Down Memoization against Bottom-Up Tabulation, analyze memory hierarchy cache locality across 2D matrix vs. 1D rolling array representations, and verify the pseudo-polynomial complexity scaling law T(n) = n · W = 100.0000 · n operations across knapsack capacity W = 100.

2. Abstract

Seven benchmark trials were generated across item scales n = 10 to n = 150 items for a 0/1 Knapsack problem with fixed capacity budget W = 100 weight units (state evaluations T from 1000 to 15000 operations). An ordinary least-squares regression of tabulation state evaluations against item count yielded an empirical complexity scaling coefficient of 100.0000 states/item, demonstrating exact agreement with the theoretical pseudo-polynomial bound (difference = 0.0000%). The empirical telemetry proves that Bottom-Up Tabulation eliminates exponential recursion trees (reducing Θ(2^n) to Θ(n·W)), achieving optimal sequential L1 cache throughput and delivering over 10^40-fold speedups over naive recursion at n = 150 items.

3. Apparatus and fixed settings

4. Theory and graph choice

Dynamic Programming (DP), formulated by Richard Bellman in the 1950s, is one of the most powerful algorithmic paradigms in modern computing, providing polynomial-time solutions to complex multi-stage decision and optimization problems. While Divide-and-Conquer algorithms partition problems into independent disjoint subproblems (as in Merge Sort or Quick Sort), Dynamic Programming addresses problems characterized by two fundamental properties: (1) Optimal Substructure, where the globally optimal solution can be constructed from optimal solutions to its constituent subproblems; and (2) Overlapping Subproblems, where a naive recursive formulation repeatedly evaluates the identical subproblem states an exponential number of times. The canonical formulation of Dynamic Programming is exemplified by the 0/1 Knapsack Problem: given n discrete items each with an integer weight w_i and valuation v_i, select a binary inclusion subset x_i ∈ {0, 1} to maximize total valuation ∑(v_i x_i) subject to a total weight capacity constraint ∑(w_i x_i) ≤ W. The Bellman optimality recurrence states that for item i and remaining weight capacity w, the maximum achievable value is DP[i][w] = max(DP[i-1][w], DP[i-1][w - w_i] + v_i) when w ≥ w_i, and DP[i-1][w] otherwise. In a naive recursive tree, this recurrence branches into 2^n paths, taking Θ(2^n) exponential time. Dynamic Programming eliminates redundant recalculation via two distinct strategies: (a) Top-Down Memoization, which retains recursive decomposition while caching computed subproblem evaluations in an auxiliary hash table or lookup array on first visit; and (b) Bottom-Up Tabulation, which systematically populates the (n + 1) × (W + 1) state matrix in topological row-major order. In Bottom-Up Tabulation, each state cell is evaluated in strict O(1) arithmetic operations, achieving a deterministic running time of T(n, W) = n · W operations. Because this running time is polynomial in the integer magnitude of W but exponential in the binary bit-length log₂ W of the capacity, 0/1 Knapsack is classified as Weakly NP-Complete, admitting pseudo-polynomial time dynamic programming. Benchmarking subproblem evaluations across systematically scaled item counts verifies the exact linear scaling law T(n) = 100.0000 · n, while elucidating critical memory hierarchy phenomena including L1/L2 cache locality, spatial prefetching, and memory reduction from Θ(n W) to Θ(W) via 1D reverse-scanned rolling buffers.

T(n) = k_dp · n + T_0 = 100.0000 · n + 0.0000 operations

The mathematical regression fits the linear model y = mx + b, where x = n represents the problem item count in items, y = T represents total elementary tabulation state evaluations, m represents the complexity scaling factor k_dp, and b represents the baseline evaluation offset (theoretically T_0 = 0.0000 states). The gradient has physical units states/item.

5. Method

  1. Allocate a contiguous 2D tabulation matrix of dimensions (n + 1) × (W + 1) for n items and capacity budget W = 100. Initialize all boundary base-case entries DP[0][w] = 0 and DP[i][0] = 0, and pre-fill memoization buffers with sentinel -1.
  2. Invoke the recursive solver for target state DP(n, W). At each call, inspect the memo table: return the cached value immediately upon a cache hit (O(1)), or evaluate subproblem branches (exclude item i vs. include item i) and write the result into the table.
  3. Execute the dual nested loops (i from 1 to n, w from 0 to W) in row-major memory order. Evaluate the Bellman recurrence relation for each cell and increment the deterministic state evaluation counter.
  4. Trace backward from cell DP[n][W] to determine the exact optimal binary selection vector x ∈ {0, 1}^n. If DP[i][w] ≠ DP[i-1][w], mark item i as included (x_i = 1) and decrement remaining capacity w ← w - w_i; otherwise mark x_i = 0.
  5. Allocate a compact 1D array of length W + 1. For each item i, iterate capacity w backward from W down to w_i, updating DP[w] = max(DP[w], DP[w - w_i] + v_i) to demonstrate Θ(W) memory compression.
  6. Record total state evaluations across item scales n ∈ [10, 20, 30, 50, 75, 100, 150]. Regress total evaluations T(n) against item count n to compute slope k_dp, intercept T_0, and coefficient of determination R².

6. Observations and calculation table

All benchmark observations use strictly controlled memory buffers. Values are recorded deterministically from the algorithmic comparator register. Residuals are computed relative to the ordinary least-squares regression line.

Table 1. Seven simulated algorithmic benchmarks; x and y represent computational state metrics.
No.Item count n (knapsack capacity W = 100 weight units) (items)Tabulation state evaluations T(n) (operations)Item count n (items)Total tabulation state evaluations T(n) = n · W (operations)Fitted yResidual
110100010.00001000.00001000.00000.0000
220200020.00002000.00002000.00000.0000
330300030.00003000.00003000.00000.0000
450500050.00005000.00005000.00000.0000
575750075.00007500.00007500.00000.0000
610010000100.000010000.000010000.00000.0000
715015000150.000015000.000015000.00000.0000

Download the sample observations (CSV) ↓

7. Worked calculation for one observation

Item Count n = 10 items; Knapsack Capacity W = 100 weight units; Total Subproblem Grid Cells (n × W) = 10 × 100 = 1000 states. Total Elementary State Transitions: T(n) = W · n = 100 × 10 = 1000 state evaluations. Verification: Bottom-up 2D tabulation iterates through i in [1 .. 10] and w in [0 .. 100], evaluating the Bellman optimality recurrence DP[i][w] = max(DP[i-1][w], DP[i-1][w - w_i] + v_i) in exactly Θ(1) arithmetic operations per cell, converging to strictly 100·n = 1000 operations.

8. Graph, gradient and final calculation

-1100.00-6.803450.0036.608000.0080.0012550.00123.4017100.00166.80Item count n (items)Total tabulation state evaluations T(n) = n · W (operations)n = 10n = 20n = 30n = 50n = 75n = 100n = 150

Circular markers represent empirical benchmark observations. The solid line represents the ordinary least-squares asymptotic linear fit.

x̄ = 62.14286; ȳ = 6214.28571
Σ(x − x̄)² = 14992.85714
Σ(x − x̄)(y − ȳ) = 1.4993e+06
m = Σ(x − x̄)(y − ȳ) / Σ(x − x̄)² = 100.00000000
b = ȳ − mx̄ = 0.00000000
k_dp = m = 100.0000 states/item; Intercept T_0 = 0.0000 states (theoretical k_dp = 100.0000, T_0 = 0.0000)

9. Uncertainty and comparison

Percentage difference = |estimate − theoretical value| / |theoretical value| × 100 = 0.0000%.

For n = 7 benchmark observations, Σresidual² = 0.00000; s² = Σresidual²/(n − 2). Gradient standard error = √[s²/Σ(x − x̄)²] = 8.1669e-09. Intercept standard error = √[s²(1/n + x̄²/Σ(x − x̄)²)] = 6.3279e-07.

Propagating the fit parameters yields a fit standard error of 8.1669e-09 states/item, with an ideal coefficient of determination R² = 1.000000.

In discrete algorithm complexity analysis, the tabulation state evaluation count T(n) = W · n = 100.0000·n for the 0/1 Knapsack Problem is an exact combinatorial invariant under fixed capacity W = 100. Unlike continuous physical instrumentation, there is no analog sensor noise, thermal drift, or calibration variance in counting discrete subproblem matrix cell evaluations. However, in physical semiconductor microprocessors, wall-clock dynamic programming execution latency is strongly modulated by memory hierarchy and pipeline dynamics: (1) CPU L1/L2 data cache hit ratios and spatial prefetching: contiguous row-major traversal (outer loop i, inner loop w) streams adjacent 8-byte cells into 64-byte L1 cache lines with ~100% prefetcher hit rates (~1–4 CPU cycles/cell), whereas transposed column-major traversal suffers catastrophic cache line thrashing and TLB page misses (~100–250 CPU cycles/cell); (2) Branch predictor mispredictions during item feasibility checks (`if (w >= w_i)`), which can stall superscalar execution pipelines by 15–20 clock cycles per mispredicted branch; (3) Memory bus transfer overhead and memory footprint: allocating a full (n + 1) × (W + 1) 2D matrix of 64-bit integers incurs DRAM memory allocation latency, which is eliminated by compressing the table into a single 1D reverse-scanned array of length W + 1 that fits entirely inside the CPU L2 cache; and (4) Call stack frame overhead in Top-Down Memoization: recursive memoization allocates AMD64 stack frames (48–64 bytes/frame) and incurs non-contiguous pointer dereferencing latency, running 2× to 4× slower than iterative Bottom-Up Tabulation. Ordinary least-squares linear regression of observed tabulation state evaluations against item count n across problem instances from 10 to 150 items yields an empirical scaling slope k_dp = 100.0000 states/item with zero residual variance (R² = 1.00000), verifying the pseudo-polynomial complexity bound Θ(n·W) with mathematical certitude.

10. Result and discussion

k_dp = 100.0000 states/item
Theoretical reference value: 100.0000 states/item

The empirical benchmark observations provide rigorous quantitative verification of Bellman's Dynamic Programming paradigm and pseudo-polynomial state complexity. In Bottom-Up Tabulation of the 0/1 Knapsack Problem with fixed capacity W = 100, each cell DP[i][w] in the (n + 1) × (W + 1) matrix represents an independent subproblem state. Because each cell evaluates the Bellman optimality recurrence DP[i][w] = max(DP[i-1][w], DP[i-1][w - w_i] + v_i) in strict O(1) arithmetic operations, the total number of evaluations T(n) = W · n = 100·n scales in exact linear proportion to the number of items. The regression slope m = 100.0000 confirms this invariant with zero residual variance (R² = 1.00000). Comparative analysis across computational models reveals profound architectural insights: Naive Recursion suffers from catastrophic exponential explosion Θ(2^n), requiring 2¹⁵⁰ ≈ 1.4 × 10⁴⁵ operations at n = 150 items—an intractable computation exceeding the age of the universe. Top-Down Memoization prunes this tree to at most n·W reachable states, but incurs significant call stack allocation (48 bytes per AMD64 frame) and pointer lookup overhead. Bottom-Up Tabulation completely eliminates stack frames, while enabling perfect sequential row-major L1 cache streaming (fetching 8 cells per 64-byte cache line). Furthermore, the investigation demonstrates how 1D reverse scanning (iterating w from W down to w_i) compresses the spatial memory footprint from Θ(n·W) down to Θ(W), keeping the entire working set resident in CPU L2 cache while strictly preserving the 0/1 non-duplication invariant. Finally, Backtracking Reconstruction proves that the exact optimal subset of items can be recovered from the 2D table in O(n) linear time, cementing Dynamic Programming as the premier optimization architecture for production resource scheduling, cryptography, and compiler instruction selection.

11. Precautions and limitations

The simulated execution environment models idealized state transitions where every table cell evaluation executes with deterministic cost of 1 operation (T(n) = n · W). In physical semiconductor microprocessors, wall-clock execution latency is modulated by CPU L1/L2 data cache hit ratios during row-major array streaming, branch predictor stalls during capacity feasibility checks (w ≥ w_i), hardware memory bus saturation during large matrix allocations, and operating system page table faults. In Bottom-Up Tabulation of the 0/1 Knapsack problem with fixed capacity W = 100 weight units, every subproblem cell DP[i][w] across the (n + 1) × (W + 1) state matrix is computed exactly once in O(1) time using the Bellman recurrence relation. Across n items, the total number of elementary state transition evaluations scales as T(n) = W · n = 100.0000 · n operations with exact theoretical intercept T_0 = 0.0000 states.

12. Conclusion

This laboratory investigation quantitatively verified the recurrence relations, state space dynamics, and memory hierarchy trade-offs of Dynamic Programming. Through systematic benchmarking across item counts from n = 10 to 150 items, we verified the empirical state scaling factor k_dp = 100.0000 states/item with an ideal R² = 1.00000. The investigation established the microarchitectural superiority of Bottom-Up Tabulation and 1D reverse-scanned rolling buffers over naive exponential recursion and recursive memoization, proving why Dynamic Programming serves as a foundational pillar of modern computer science, computational genomics, and algorithmic operations research.