algorithms_edu/problems/dp/
knapsack.rs1use std::cmp::max;
12
13pub struct Item {
14 value: usize,
15 weight: usize,
16}
17
18impl Item {
19 pub fn new(value: usize, weight: usize) -> Self {
20 Self { value, weight }
21 }
22}
23
24pub fn knapsack(capacity: usize, items: &[Item]) -> (usize, Vec<usize>) {
25 let m = items.len();
26 let n = capacity;
27 let mut dp = vec![vec![0; n + 1]; m + 1];
30 for i in 1..=m {
31 let v = items[i - 1].value;
32 let w = items[i - 1].weight;
33 for j in 0..w {
34 dp[i][j] = dp[i - 1][j];
35 }
36 for j in w..=n {
37 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w] + v);
38 }
39 }
40
41 let mut selection = Vec::new();
42
43 let mut sz = n;
47 for i in (1..=m).rev() {
48 if dp[i][sz] != dp[i - 1][sz] {
49 let item_index = i - 1;
50 selection.push(item_index);
51 sz -= items[item_index].weight
52 }
53 }
54
55 (dp[m][n], selection)
56}
57
58pub fn knapsack_value_only(capacity: usize, items: &[Item]) -> usize {
59 let n = capacity;
60 let mut prev = vec![0; n + 1];
64 let mut curr;
65 for &Item { value, weight } in items {
66 curr = vec![0; n + 1];
67 curr[..weight].clone_from_slice(&prev[..weight]);
68 for j in weight..=n {
69 curr[j] = max(prev[j], prev[j - weight] + value);
70 }
71 std::mem::swap(&mut prev, &mut curr);
72 }
73 prev[n]
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 #[test]
80 fn test_knapsack() {
81 let items = vec![
82 Item::new(2, 3),
83 Item::new(2, 1),
84 Item::new(4, 3),
85 Item::new(5, 4),
86 Item::new(3, 2),
87 ];
88 let (max_val, selection) = knapsack(7, &items);
89 assert_eq!(max_val, 10);
90 assert_eq!(&selection, &[4, 3, 1]);
91
92 assert_eq!(knapsack_value_only(7, &items), 10);
93 }
94}