|
| 1 | +//! Solves the rod-cutting problem |
| 2 | +use std::cmp::max; |
| 3 | + |
| 4 | +/// `rod_cut(p)` returns the maximum possible profit if a rod of length `n` = `p.len()` |
| 5 | +/// is cut into up to `n` pieces, where the profit gained from each piece of length |
| 6 | +/// `l` is determined by `p[l - 1]` and the total profit is the sum of the profit |
| 7 | +/// gained from each piece. |
| 8 | +/// |
| 9 | +/// # Arguments |
| 10 | +/// - `p` - profit for rods of length 1 to n inclusive |
| 11 | +/// |
| 12 | +/// # Complexity |
| 13 | +/// - time complexity: O(n^2), |
| 14 | +/// - space complexity: O(n^2), |
| 15 | +/// |
| 16 | +/// where n is the length of `p`. |
| 17 | +pub fn rod_cut(p: &[usize]) -> usize { |
| 18 | + let n = p.len(); |
| 19 | + // f is the dynamic programming table |
| 20 | + let mut f = vec![0; n]; |
| 21 | + |
| 22 | + for i in 0..n { |
| 23 | + let mut max_price = p[i]; |
| 24 | + for j in 1..=i { |
| 25 | + max_price = max(max_price, p[j - 1] + f[i - j]); |
| 26 | + } |
| 27 | + f[i] = max_price; |
| 28 | + } |
| 29 | + |
| 30 | + // accomodate for input with length zero |
| 31 | + if n != 0 { |
| 32 | + f[n - 1] |
| 33 | + } else { |
| 34 | + 0 |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +#[cfg(test)] |
| 39 | +mod tests { |
| 40 | + use super::rod_cut; |
| 41 | + |
| 42 | + #[test] |
| 43 | + fn test_rod_cut() { |
| 44 | + assert_eq!(0, rod_cut(&[])); |
| 45 | + assert_eq!(15, rod_cut(&[5, 8, 2])); |
| 46 | + assert_eq!(10, rod_cut(&[1, 5, 8, 9])); |
| 47 | + assert_eq!(25, rod_cut(&[5, 8, 2, 1, 7])); |
| 48 | + assert_eq!(87, rod_cut(&[0, 0, 0, 0, 0, 87])); |
| 49 | + assert_eq!(49, rod_cut(&[7, 6, 5, 4, 3, 2, 1])); |
| 50 | + assert_eq!(22, rod_cut(&[1, 5, 8, 9, 10, 17, 17, 20])); |
| 51 | + assert_eq!(60, rod_cut(&[6, 4, 8, 2, 5, 8, 2, 3, 7, 11])); |
| 52 | + assert_eq!(30, rod_cut(&[1, 5, 8, 9, 10, 17, 17, 20, 24, 30])); |
| 53 | + assert_eq!(12, rod_cut(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])); |
| 54 | + } |
| 55 | +} |
0 commit comments