-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUnboundedKnapsack.java
133 lines (116 loc) · 4.48 KB
/
UnboundedKnapsack.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package dynamicproggamming.advanced;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
// Given a list of N items, and a backpack with a
// limited capacity, return the maximum total profit that
// can be contained in the backpack. The i-th item's profit
// is profit[i] and it's weight is weight[i]. Assume you can
// only add each item to the bag at most one time.
public class UnboundedKnapsack {
// Brute force Solution
// Time: O(2^n), Space: O(n)
// Where n is the number of items.
public static int dfs(List<Integer> profit, List<Integer> weight, int capacity) {
return dfsHelper(0, profit, weight, capacity);
}
public static int dfsHelper(int i, List<Integer> profit, List<Integer> weight, int capacity) {
if (i == profit.size()) {
return 0;
}
// Skip item i
int maxProfit = dfsHelper(i + 1, profit, weight, capacity);
// Include item i
int newCap = capacity - weight.get(i);
if (newCap >= 0) {
int p = profit.get(i) + dfsHelper(i, profit, weight, newCap);
// Compute the max
maxProfit = Math.max(maxProfit, p);
}
return maxProfit;
}
// Memoization Solution
// Time: O(n * m), Space: O(n * m)
// Where n is the number of items & m is the capacity.
public static int memoization(List<Integer> profit, List<Integer> weight, int capacity) {
// A 2d array, with N rows and M + 1 columns, init with -1's
int N = profit.size(), M = capacity;
List<Integer[]> cache = new ArrayList<>();
for (int row = 0; row < N; row++) {
cache.add(row, new Integer[M + 1]);
Arrays.fill(cache.get(row), -1);
}
return memoHelper(0, profit, weight, capacity, cache);
}
public static int memoHelper(int i, List<Integer> profit, List<Integer> weight,
int capacity, List<Integer[]> cache) {
if (i == profit.size()) {
return 0;
}
if (cache.get(i)[capacity] != -1) {
return cache.get(i)[capacity];
}
// Skip item i
cache.get(i)[capacity] = memoHelper(i + 1, profit, weight, capacity, cache);
// Include item i
int newCap = capacity - weight.get(i);
if (newCap >= 0) {
int p = profit.get(i) + memoHelper(i, profit, weight, newCap, cache);
// Compute the max
cache.get(i)[capacity] = Math.max(cache.get(i)[capacity], p);
}
return cache.get(i)[capacity];
}
// Dynamic Programming Solution
// Time: O(n * m), Space: O(n * m)
// Where n is the number of items & m is the capacity.
public static int dp(List<Integer> profit, List<Integer> weight, int capacity) {
int N = profit.size(), M = capacity;
List<Integer[]> dp = new ArrayList<>();
for (int row = 0; row < N; row++) {
dp.add(row, new Integer[M + 1]);
Arrays.fill(dp.get(row), 0);
}
// Fill the first column and row to reduce edge cases
for (int i = 0; i < N; i++) {
dp.get(i)[0] = 0;
}
for (int c = 0; c <= M; c++) {
if (weight.get(0) <= c) {
dp.get(0)[c] = (c / weight.get(0)) * profit.get(0);
}
}
for (int i = 1; i < N; i++) {
for (int c = 1; c <= M; c++) {
int skip = dp.get(i-1)[c];
int include = 0;
if (c - weight.get(i) >= 0) {
include = profit.get(i) + dp.get(i)[c - weight.get(i)];
}
dp.get(i)[c] = Math.max(include, skip);
}
}
return dp.get(N-1)[M];
}
// Memory optimized Dynamic Programming Solution
// Time: O(n * m), Space: O(m)
public static int optimizedDp(List<Integer> profit, List<Integer> weight, int capacity) {
int N = profit.size(), M = capacity;
Integer[] dp = new Integer[M+1];
Arrays.fill(dp, 0);
for (int i = 1; i < N; i++) {
Integer[] curRow = new Integer[M+1];
Arrays.fill(curRow, 0);
for (int c = 1; c <= M; c++) {
int skip = dp[c];
int include = 0;
if (c - weight.get(i) >= 0) {
include = profit.get(i) + curRow[c - weight.get(i)];
}
curRow[c] = Math.max(include, skip);
}
dp = curRow;
}
return dp[M];
}
}