-
-
Notifications
You must be signed in to change notification settings - Fork 342
feat- 0/1 Knapsack Problem (Dynamic Programming) in R #167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
siriak
merged 3 commits into
TheAlgorithms:master
from
Sachinn-64:algo/knapsack-implementation
Oct 8, 2025
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,194 @@ | ||
| # 0/1 Knapsack Problem (Dynamic Programming) | ||
| # | ||
| # The 0/1 Knapsack problem is one of the most classic problems in dynamic programming. | ||
| # Given a set of items, each with a weight and a value, determine the maximum total value | ||
| # you can obtain by putting items in a knapsack with a fixed capacity. Each item can | ||
| # either be included (1) or excluded (0) — hence the name "0/1". | ||
| # | ||
| # Time Complexity: O(n * W) where n = number of items, W = knapsack capacity | ||
| # Space Complexity: O(n * W) for full DP table, O(W) for optimized version | ||
| # | ||
| # Applications: | ||
| # - Budget allocation problems | ||
| # - Resource optimization (CPU scheduling, project selection) | ||
| # - Portfolio selection in finance | ||
| # - Cargo loading and packing | ||
| # - Subset optimization in AI planning | ||
|
|
||
| # Classic DP solution for 0/1 Knapsack | ||
| knapsack_01 <- function(weights, values, capacity) { | ||
| #' Solve 0/1 Knapsack Problem using Dynamic Programming | ||
| #' @param weights: Numeric vector of item weights | ||
| #' @param values: Numeric vector of item values | ||
| #' @param capacity: Maximum weight capacity of the knapsack | ||
| #' @return: List containing max value, selected items, and DP table | ||
|
|
||
| n <- length(values) | ||
|
|
||
| # Handle edge case | ||
| if (n == 0 || capacity == 0) { | ||
| return(list( | ||
| max_value = 0, | ||
| selected_items = c(), | ||
| dp_table = matrix(0, nrow = n + 1, ncol = capacity + 1) | ||
Sachinn-64 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| )) | ||
| } | ||
|
|
||
| # Create DP table: dp[i, w] = max value using first i items with capacity w | ||
| dp <- matrix(0, nrow = n + 1, ncol = capacity + 1) | ||
|
|
||
| # Fill DP table | ||
| for (i in 1:n) { | ||
| for (w in 0:capacity) { | ||
| # Don't include item i | ||
| dp[i + 1, w + 1] <- dp[i, w + 1] | ||
|
|
||
| # Include item i (if it fits) | ||
| if (weights[i] <= w) { | ||
| include_value <- values[i] + dp[i, w - weights[i] + 1] | ||
| dp[i + 1, w + 1] <- max(dp[i + 1, w + 1], include_value) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| # Backtrack to find selected items | ||
| selected <- c() | ||
| i <- n | ||
| w <- capacity | ||
|
|
||
| while (i > 0 && w > 0) { | ||
| # If value came from including item i | ||
| if (dp[i + 1, w + 1] != dp[i, w + 1]) { | ||
| selected <- c(i, selected) | ||
| w <- w - weights[i] | ||
| } | ||
| i <- i - 1 | ||
| } | ||
|
|
||
| return(list( | ||
| max_value = dp[n + 1, capacity + 1], | ||
| selected_items = selected, | ||
| dp_table = dp | ||
| )) | ||
| } | ||
|
|
||
| # Space-optimized version using only 1D array | ||
| knapsack_01_optimized <- function(weights, values, capacity) { | ||
| #' Space optimized 0/1 Knapsack using 1D array | ||
| #' @return: Maximum total value | ||
Sachinn-64 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| n <- length(values) | ||
|
|
||
| if (n == 0 || capacity == 0) { | ||
| return(0) | ||
| } | ||
|
|
||
| dp <- rep(0, capacity + 1) | ||
|
|
||
| # Process each item | ||
| for (i in 1:n) { | ||
| # Traverse from right to left to avoid overwriting needed values | ||
| for (w in capacity:weights[i]) { | ||
| if (weights[i] <= w) { | ||
| dp[w + 1] <- max(dp[w + 1], values[i] + dp[w - weights[i] + 1]) | ||
| } | ||
Sachinn-64 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| return(dp[capacity + 1]) | ||
| } | ||
|
|
||
| # Helper function to print DP table | ||
| print_knapsack_dp <- function(dp_table, weights, values, capacity) { | ||
| cat("DP Table for 0/1 Knapsack:\n") | ||
| cat("Weights:", paste(weights, collapse = ", "), "\n") | ||
| cat("Values :", paste(values, collapse = ", "), "\n") | ||
| cat("Capacity:", capacity, "\n\n") | ||
|
|
||
| # Print capacity headers | ||
| cat(" ") | ||
| cat(paste(sprintf("%3d", 0:capacity), collapse = " ")) | ||
| cat("\n") | ||
| cat(paste(rep("-", 8 + 4 * (capacity + 1)), collapse = ""), "\n") | ||
|
|
||
| for (i in 1:nrow(dp_table)) { | ||
| cat(sprintf("Item %2d | ", i - 1)) | ||
| cat(paste(sprintf("%3d", dp_table[i, ]), collapse = " ")) | ||
| cat("\n") | ||
| } | ||
| cat("\n") | ||
| } | ||
|
|
||
| # =========================== | ||
| # Example Usage & Testing | ||
| # =========================== | ||
| cat("=== 0/1 Knapsack Problem (Dynamic Programming) ===\n\n") | ||
|
|
||
| # Test 1: Basic Example | ||
| weights <- c(1, 3, 4, 5) | ||
| values <- c(1, 4, 5, 7) | ||
| capacity <- 7 | ||
|
|
||
| cat("Test 1: Basic Example\n") | ||
| cat("Weights:", paste(weights, collapse = ", "), "\n") | ||
| cat("Values :", paste(values, collapse = ", "), "\n") | ||
| cat("Capacity:", capacity, "\n\n") | ||
|
|
||
| result <- knapsack_01(weights, values, capacity) | ||
| print_knapsack_dp(result$dp_table, weights, values, capacity) | ||
| cat("Maximum Value:", result$max_value, "\n") | ||
| cat("Selected Item Indices:", paste(result$selected_items, collapse = ", "), "\n") | ||
| cat("Total Weight:", sum(weights[result$selected_items]), "\n") | ||
| cat("Total Value:", sum(values[result$selected_items]), "\n\n") | ||
|
|
||
| # Test 2: Space Optimized Example | ||
| cat("Test 2: Space Optimized Version\n") | ||
| max_val_opt <- knapsack_01_optimized(weights, values, capacity) | ||
| cat("Maximum Value (Optimized):", max_val_opt, "\n") | ||
| cat("Verification: Both methods match:", result$max_value == max_val_opt, "\n\n") | ||
|
|
||
| # Test 3: Larger Dataset | ||
| cat("Test 3: Larger Dataset\n") | ||
| set.seed(42) | ||
| weights <- sample(1:15, 10) | ||
| values <- sample(10:100, 10) | ||
| capacity <- 35 | ||
|
|
||
| cat("Weights:", paste(weights, collapse = ", "), "\n") | ||
| cat("Values :", paste(values, collapse = ", "), "\n") | ||
| cat("Capacity:", capacity, "\n\n") | ||
|
|
||
| large_result <- knapsack_01(weights, values, capacity) | ||
| cat("Maximum Value:", large_result$max_value, "\n") | ||
| cat("Selected Items:", paste(large_result$selected_items, collapse = ", "), "\n") | ||
| cat("Total Weight:", sum(weights[large_result$selected_items]), "\n\n") | ||
|
|
||
| # Test 4: Edge Cases | ||
| cat("Test 4: Edge Cases\n") | ||
| cat("Empty items:", knapsack_01(c(), c(), 10)$max_value, "\n") | ||
siriak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| cat("Zero capacity:", knapsack_01(weights, values, 0)$max_value, "\n") | ||
| cat("Single item fits:", knapsack_01(c(5), c(10), 10)$max_value, "\n") | ||
| cat("Single item doesn't fit:", knapsack_01(c(10), c(10), 5)$max_value, "\n\n") | ||
|
|
||
| # Test 5: Performance Check | ||
| cat("Test 5: Performance Comparison (n=100)\n") | ||
| n <- 100 | ||
| weights <- sample(1:15, n, replace = TRUE) | ||
| values <- sample(10:100, n, replace = TRUE) | ||
| capacity <- 200 | ||
|
|
||
| start_time <- Sys.time() | ||
| res_std <- knapsack_01_optimized(weights, values, capacity) | ||
| std_time <- as.numeric(Sys.time() - start_time, units = "secs") | ||
|
|
||
| cat("Optimized DP result:", res_std, "\n") | ||
| cat("Time taken:", sprintf("%.4f sec", std_time), "\n") | ||
|
|
||
| # Verify correctness | ||
| cat("\nVerifying correctness with full DP:\n") | ||
| start_time <- Sys.time() | ||
| res_full <- knapsack_01(weights, values, capacity) | ||
| full_time <- as.numeric(Sys.time() - start_time, units = "secs") | ||
| cat("Full DP result:", res_full$max_value, "\n") | ||
| cat("Time taken:", sprintf("%.4f sec", full_time), "\n") | ||
| cat("Results match:", res_std == res_full$max_value, "\n") | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.