The 0-1 Knapsack problem is a classical optimization problem in computer science. It consists of selecting a set of items with individual weights and profits to maximize the total profit while satisfying a fixed capacity constraint. In other words, we need to select items such that their total weight does not exceed the capacity of the satchel while maximizing the total profit. The letter “0-1” in the problem name means that you can either include an item (1) or exclude it (0), but you cannot take fractional items.
It is NP-hard, i.e., there is no known polynomial-time algorithm for its optimal solution. However, it can be solved efficiently by backtracking, a systematic algorithmic approach to find all possible solutions. Here we present a C implementation of the backtracking method for solving the 0-1 Knapsack problem.
The Backtracking Approach
The presented C code implements the backtracking algorithm to find the optimal solution to the 0-1 Knapsack problem. The essence of the algorithm is to search through all possible combinations of items, respecting the knapsack capacity constraint, and maximizing the total profit.
Let’s break down the main components of the code:
- Defining the structure of backpack items. We represent each item as a structure containing information about its identifier, weight, profit, and profit density (per unit weight);
- Sorting items by profit density. Items are sorted in descending order of density. This means that goods with the highest density are considered first, which increases the probability of maximizing profit quickly;
- Boundary function. The boundary function is used to estimate the upper bound on the profit achievable under the current satchel condition. This estimate reduces the search space by eliminating paths that cannot lead to an optimal solution;
- Recursive function. The knapsack_recursive function is the heart of the algorithm. It tries all possible combinations of items, keeping track of the current weight, profit, and current state of the knapsack. When it reaches a leaf node of the search tree, it checks whether this solution is better than the previously found best solution;
- The basic satchel function. The satchel function initializes the algorithm and returns the maximum profit found. It manages memory allocation for data structures and calls a recursive function.
Now that we have understood the basic approaches, let’s move on to examples.
Example Usage
Included with the code is an example program demonstrating the use of the backtracking algorithm to solve the 0-1 Knapsack problem. In this example, a set of items with corresponding weights and incomes is given. The capacity of the knapsack is set to 7 items. The code then calculates and prints the maximum revenue and the items included in the optimal solution.
Here are some code examples that illustrate the use of the backtracking algorithm to solve the 0-1 Knapsack problem in C:
Example Code for Defining Weights and Profits
#include <stdio.h>
#include <stdlib.h>
int main(void) {
double weights[] = {3, 5, 2, 1};
double profits[] = {9, 10, 7, 4};
const size_t n = sizeof(profits) / sizeof(profits[0]);
const double capacity = 7;
// Your code to call the knapsack function and handle the result goes here
return 0;
}
In this code we define the weights and profits of the items, the number of items (n), and the capacity of the satchel. Replace the comment with the code to call the knapsack function and process the result.
Function Call to Solve the Knapsack Problem
To use the knapsack function defined earlier, you can include the following code snippet in the previous example:
unsigned int *max_knapsack;
double max_profit = knapsack(weights, profits, n, capacity, &max_knapsack);
// Print the maximum profit
printf("Profit: %.2f\n", max_profit);
// Print the items included in the optimal solution
printf("Knapsack contains:\n");
for (unsigned int i = 0; i < n; i++) {
if (max_knapsack[i] == 1) {
printf("Item %u with weight %.2f and profit %.2f\n", i, weights[i], profits[i]);
}
}
// Don't forget to free the allocated memory for max_knapsack
free(max_knapsack);
This code calls the backpack function to find the optimal solution given weights. It then outputs the maximum profit and the number of items included in the knapsack to the console.
By combining these code snippets, you can create a complete program to solve the 0-1 Knapsack problem using a backtracking algorithm in C.
Summarize
The 0-1 Knapsack problem is a complex optimization problem that has many real-world applications such as resource allocation and scheduling. Although it is NP-hard, backtracking provides an efficient approach to finding near-optimal solutions.
The C code presented here demonstrates an efficient way to solve this problem by systematically enumerating all possible solutions. Understanding this code can be a valuable aid in solving similar combinatorial optimization problems and developing algorithms for practical use.