1use crate::types::Item;
2use std::cmp::max;
3
4pub fn knapsack(capacity: u8, items: &[Item<u8, u64>]) -> Result<(u64, usize), String> {
5 let mut items = items.to_vec();
7 items.sort_by(|a, b| a.weight.cmp(&b.weight));
8
9 let max_overflow = items
10 .first()
11 .unwrap_or(&Item {
12 weight: 0,
13 value: 0,
14 })
15 .weight as usize;
16
17 let capacity = capacity as usize;
18 let mut dp = vec![0; capacity + max_overflow + 1];
19 let mut weight = vec![0; capacity + max_overflow + 1];
20
21 if let Some(item) = items.first() {
23 if item.weight == 0 {
24 return Err("Item weight cannot be 0".to_string());
25 }
26 }
27
28 for i in 0..=(capacity + max_overflow) {
29 for item in &items {
30 if item.weight as usize > i {
31 break;
33 } else {
34 if i - item.weight as usize == 0 || weight[i - item.weight as usize] != 0 {
37 match item.value.checked_add(dp[i - item.weight as usize]) {
38 Some(use_item_value) => {
39 dp[i] = max(dp[i], use_item_value);
41 weight[i] = max(
42 weight[i],
43 weight[i - item.weight as usize] + item.weight as usize,
44 )
45 }
46 None => {
47 return Err("Value overflow".to_string());
48 }
49 };
50 }
51 }
52 }
53 if i >= capacity && weight[i] >= capacity {
54 return Ok((dp[i], i));
55 }
56 }
57
58 if items.is_empty() {
59 return Ok((0, 0));
60 }
61
62 Err("Unable to reach threshold".to_string())
63}