0/1 Knapsack
Problem
There are n items. Item i has the weight w[i] and the value v[i]. The bag can carry a total weight of at most W. Each item can be taken once or not at all. The first line has n and W. The second line has the weights. The third line has the values. Print the maximum total value.
Constraints
- 1 <= n <= 100
- 0 <= W <= 10^4
Examples
Input
3 50 10 20 30 60 100 120
Output
220
Solutions
For each item we decide: leave it, or take it and add its value to the best result for the smaller capacity. Going backwards over the capacities makes sure that an item is not used twice. One array is enough.
/*
* Problem : Maximum value in the bag.
* Input : Three lines: n and W, weights, values.
* Output : The maximum value.
* Approach: Take or leave each item.
* Time : O(n * W)
* Space : O(W)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// This method solves the task. It receives the input and returns the answer.
static int solve(String[] lines) {
String[] header = lines[0].split(" ");
int n = Integer.parseInt(header[0]);
int capacity = Integer.parseInt(header[1]);
String[] weightText = lines[1].split(" ");
String[] valueText = lines[2].split(" ");
// Step 1: best[c] = the best value for a bag with the capacity c. At the start the bag is empty, so all values are 0.
int[] best = new int[capacity + 1];
for (int i = 0; i < n; i++) {
int weight = Integer.parseInt(weightText[i]);
int value = Integer.parseInt(valueText[i]);
// Step 2: Go from the largest capacity to the smallest. This way, every item is used at most once.
for (int c = capacity; c >= weight; c--) {
// Step 3: Take the item (value plus the best for the remaining capacity) or leave it.
best[c] = Math.max(best[c], best[c - weight] + value);
}
}
return best[capacity];
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(solve(lines));
}
}
Hints (1)
- Why do we loop over the capacity from large to small?