扔鸡蛋(Egg dropping)

  1. /// # Egg Dropping Puzzle
  2. /// `egg_drop(eggs, floors)` returns the least number of egg droppings
  3. /// required to determine the highest floor from which an egg will not
  4. /// break upon dropping
  5. ///
  6. /// Assumptions: n > 0
  7. pub fn egg_drop(eggs: u32, floors: u32) -> u32 {
  8. assert!(eggs > 0);
  9. // Explicity handle edge cases (optional)
  10. if eggs == 1 || floors == 0 || floors == 1 {
  11. return floors;
  12. }
  13. let eggs_index = eggs as usize;
  14. let floors_index = floors as usize;
  15. // Store solutions to subproblems in 2D Vec,
  16. // where egg_drops[i][j] represents the solution to the egg dropping
  17. // problem with i eggs and j floors
  18. let mut egg_drops: Vec<Vec<u32>> = vec![vec![0; floors_index + 1]; eggs_index + 1];
  19. // Assign solutions for egg_drop(n, 0) = 0, egg_drop(n, 1) = 1
  20. for egg_drop in egg_drops.iter_mut().skip(1) {
  21. egg_drop[0] = 0;
  22. egg_drop[1] = 1;
  23. }
  24. // Assign solutions to egg_drop(1, k) = k
  25. for j in 1..=floors_index {
  26. egg_drops[1][j] = j as u32;
  27. }
  28. // Complete solutions vector using optimal substructure property
  29. for i in 2..=eggs_index {
  30. for j in 2..=floors_index {
  31. egg_drops[i][j] = std::u32::MAX;
  32. for k in 1..=j {
  33. let res = 1 + std::cmp::max(egg_drops[i - 1][k - 1], egg_drops[i][j - k]);
  34. if res < egg_drops[i][j] {
  35. egg_drops[i][j] = res;
  36. }
  37. }
  38. }
  39. }
  40. egg_drops[eggs_index][floors_index]
  41. }
  42. #[cfg(test)]
  43. mod tests {
  44. use super::egg_drop;
  45. #[test]
  46. fn zero_floors() {
  47. assert_eq!(egg_drop(5, 0), 0);
  48. }
  49. #[test]
  50. fn one_egg() {
  51. assert_eq!(egg_drop(1, 8), 8);
  52. }
  53. #[test]
  54. fn eggs2_floors2() {
  55. assert_eq!(egg_drop(2, 2), 2);
  56. }
  57. #[test]
  58. fn eggs3_floors5() {
  59. assert_eq!(egg_drop(3, 5), 3);
  60. }
  61. #[test]
  62. fn eggs2_floors10() {
  63. assert_eq!(egg_drop(2, 10), 4);
  64. }
  65. #[test]
  66. fn eggs2_floors36() {
  67. assert_eq!(egg_drop(2, 36), 8);
  68. }
  69. #[test]
  70. fn large_floors() {
  71. assert_eq!(egg_drop(2, 100), 14);
  72. }
  73. }