|
| 1 | +package algorithms.dynamic |
| 2 | + |
| 3 | +/// Subset Sum / Knapsack Problem (without values) |
| 4 | +/// Computes the maximal reachable weight (i.e. the largest sum of selected items) that does not exceed the capacity W. |
| 5 | +/// Given an array of positive integers `weights` (each > 0) and a capacity `W`, |
| 6 | +/// the function determines the greatest weight sum obtainable by a subset of the items such that the sum is ≤ W. |
| 7 | +/// |
| 8 | +/// Uses a 1D boolean DP array where: |
| 9 | +/// - dp(w) is true if weight w is reachable using a subset of the items. |
| 10 | +/// The recurrence is: |
| 11 | +/// - Base Case: dp(0) = true (the empty subset) |
| 12 | +/// - For each item weight and for each w from W down to that weight: |
| 13 | +/// if dp(w - weight) is true then dp(w) becomes true. |
| 14 | +/// |
| 15 | +/// Time Complexity: O(n * W), where n is the number of items and W is the capacity. |
| 16 | +def maxReachableWeight(weights: Array[Int], W: Int): (Int, Array[Boolean]) = { |
| 17 | + // Initialize DP array: only 0 is reachable at the start. |
| 18 | + val dp: Array[Boolean] = Array.fill(W + 1)(false) |
| 19 | + dp(0) = true |
| 20 | + |
| 21 | + // Process each weight (each item is used at most once) |
| 22 | + for (weight <- weights) { |
| 23 | + // Loop backwards to avoid using the same item more than once |
| 24 | + for (w <- W to weight by -1) { |
| 25 | + if (dp(w - weight)) { |
| 26 | + dp(w) = true |
| 27 | + } |
| 28 | + } |
| 29 | + } |
| 30 | + |
| 31 | + // Find the maximum reachable weight ≤ W by scanning from W down to 0. |
| 32 | + for (w <- W to 0 by -1) { |
| 33 | + if (dp(w)) return (w, dp) |
| 34 | + } |
| 35 | + // In any case, dp(0) is true, so the function always returns within the loop. |
| 36 | + (0, dp) |
| 37 | +} |
| 38 | + |
| 39 | +@main |
| 40 | +def mainMaxReachableWeight(): Unit = { |
| 41 | + // Example instance: four objects with weights 2, 5, 3, and 6, and capacity W = 12. |
| 42 | + val weights = Array(2, 5, 3, 6) |
| 43 | + val W = 12 |
| 44 | + val (maxWeight, dp) = maxReachableWeight(weights, W) |
| 45 | + |
| 46 | + println(s"Maximum reachable weight not exceeding $W is: $maxWeight") |
| 47 | + println("DP Array (Reachable Weights):") |
| 48 | + // Display the reachability status for weights 0 to W. |
| 49 | + for (w <- 0 to W) { |
| 50 | + println(s"Weight $w: ${if (dp(w)) "reachable" else "not reachable"}") |
| 51 | + } |
| 52 | +} |
0 commit comments