<算法> 猴子运香蕉,你能搞清楚吗

703 阅读2分钟

小知识,大挑战!本文正在参与“   程序员必备小知识

本文同时参与 「掘力星计划」   ,赢取创作大礼包,挑战创作激励金

一个猴子身带100个香蕉,他距离家50米。这个猴子要带香蕉回去,但是他一次最多只能背50个香蕉,而且,每走一米他就要吃掉一个香蕉(往 回走也要吃香蕉)。这个猴子最后最多可以带多少个香蕉到家??

public class Mb {
   public static void main(String... arg) {
      recursiveMove(100, 50, 50, 1);
      move(100, 50, 50, 1);
      //recursiveMove(3000, 1000, 1000, 1);
   }
 
   /**
    * 循环算法
    * @param total 总数量
    * @param capacity 每次最多搬多少个
    * @param distance 距离
    * @param eatNum 每走一米吃的数量
    * @return 到家剩余的数量
    **/
   public static void move(int total, int capacity, int distance, int eatNum) {
 
      // 已经搬到的位置, 即搬了几米
      int location = 0;
 
      // 每次搬运起始点剩的数量
      int currentStartNum = total;
 
      // 每次搬运终点剩的数量
      int currentEndNum = 0;
 
      // 所有剩余香蕉移动一个位置
      while (location < distance && currentStartNum > eatNum) {
         System.out.println("当前所在位置" + location + "剩下" + currentStartNum + "个香蕉");
 
         // 每筐香蕉移动一个位置, 是移动一个位置的具体细节
         // 如果搬运起点还剩2个,返回去已经没有意义
         while (currentStartNum > eatNum * 2) {
 
            if (currentStartNum > capacity) {
               moveOnePosition(location, location + 1, capacity, eatNum);
               currentStartNum -= capacity;
               currentEndNum += capacity - eatNum;
            } else {
               moveOnePosition(location, location + 1, currentStartNum, eatNum);
               // 直接向前走
               currentEndNum += currentStartNum - eatNum;
               currentStartNum = 0;
            }
 
            // 需不需要搬起点剩下的, 即需不需要返回
            if (currentStartNum > eatNum * 2) {
               moveOnePosition(location + 1, location, -1, eatNum);
               currentEndNum -= eatNum;
            }
         }
 
         currentStartNum = currentEndNum;
         currentEndNum = 0;
         location++;
      }
 
      if (location < distance) {
         System.out.println("---猴子爬不到终点,饿死了---");
      } else {
         System.out.println("成功走到终点, 剩余" + currentStartNum + "个");
      }
   }
 
   /**
    * 递归算法
    * @param total 总数量
    * @param capacity 每次最多搬多少个
    * @param distance 距离
    * @param eatNum 每走一米吃的数量
    * @return 到家剩余的数量
    **/
   public static void recursiveMove(Integer total, Integer capacity, Integer distance, Integer eatNum) {
 
      // 已经搬到的位置
      Integer location = 0;
 
      // 每次搬运起始点剩的数量
      Integer currentStartNum = total;
 
      // 每次搬运终点剩的数量
      Integer currentEndNum = 0;
 
      stepMove(location, distance, capacity, currentStartNum, currentEndNum, eatNum);
   }
 
   private static void stepMove(int location, int distance, int capacity, int currentStartNum, int currentEndNum, int eatNum) {
      if (location < distance && currentStartNum > eatNum) {
         // 所有剩余香蕉移动一个位置
         System.out.println("当前所在位置" + location + "剩下" + currentStartNum + "个香蕉");
 
         // 每筐香蕉移动一个位置, 是移动一个位置的具体细节
         // 如果搬运起点还剩2个,返回去已经没有意义
         currentEndNum = miniStep(location, distance, capacity, currentStartNum, currentEndNum, eatNum);
 
         // 向前挪一步
         currentStartNum = currentEndNum;
         currentEndNum = 0;
         location++;
 
         stepMove(location, distance, capacity, currentStartNum, currentEndNum, eatNum);
      } else {
         if (location < distance) {
            System.out.println("---猴子爬不到终点,饿死了---");
         } else {
            System.out.println("成功走到终点, 剩余" + currentStartNum + "个");
         }
      }
   }
 
   private static int miniStep(int location, int distance, int capacity, int currentStartNum, int currentEndNum, int eatNum) {
      if (currentStartNum > eatNum * 2) {
 
         if (currentStartNum > capacity) {
            moveOnePosition(location, location + 1, capacity, eatNum);
            currentStartNum -= capacity;
            currentEndNum += capacity - eatNum;
         } else {
            moveOnePosition(location, location + 1, currentStartNum, eatNum);
            // 直接向前走
            currentEndNum += currentStartNum - eatNum;
            currentStartNum = 0;
         }
 
         // 需不需要搬起点剩下的, 即需不需要返回
         if (currentStartNum > eatNum * 2) {
            moveOnePosition(location + 1, location, -1, eatNum);
            currentEndNum -= eatNum;
         }
 
         return miniStep(location, distance, capacity, currentStartNum, currentEndNum, eatNum);
      } else {
         return currentEndNum;
      }
   }
 
   /**
    * @param from 起始位置
    * @param to 目标位置
    * @param count 搬的数量
    * @param eatNum 搬一米吃的数量
    */
   private static void moveOnePosition(int from, int to, int count, int eatNum) {
      if (count != -1) {
         System.out.println("从位置" + from + "搬" + count + "个到位置" + to + ", 吃掉" + eatNum + "个");
      } else {
         System.out.println("从位置" + from + "返回到位置" + to + ", 吃掉 " + eatNum + "个");
      }
   }
 
}