问题描述:
一个小猴子边上有100根香蕉,它要走过50米才能到家,每次它最多搬50根香蕉。它每走1米就要吃掉一根,请问它最多能把多少根香蕉搬到家里呢?
提示:他可以把香蕉放下往返的走,但是必须保证它每走一米都能有香蕉吃。也可以走到n米时,放下一些香蕉,拿着n根香蕉走回去重新搬50根。
程序实现:
接口:
/**
* 接口类
*
* @author song
*/
public interface MonkeysMoveBananas {
/**
* 移动接口
*
* @param num 总数量 如100
* @param maxNum 每次最多搬多少个 如50个
* @param distance 距离 如50
* @param eatNum 每走一米吃的数量, 如1个
* @return 到家剩余的数量,或者无法再搬香蕉时剩余的数量
*/
int move(int num, int maxNum, int distance, int eatNum);
}
实现类:
/**
* 猴子搬香蕉问题实现类
*
* @author song
*/
public class MonkeysMoveBananasImpl implements MonkeysMoveBananas {
/**
* @param num 总数量 如100
* @param maxNum 每次最多搬多少个 如50个
* @param distance 距离 如50
* @param eatNum 每走一米吃的数量, 如1个
* @return 到家剩余的数量,或者无法再搬香蕉时剩余的数量
*/
@Override
public int move(int num, int maxNum, int distance, int eatNum) {
// 已经搬到的位置, 即搬了几米
int location = 0;
// 每次搬运起始点剩的数量
int currentNumberS = num;
// 每次搬运终点剩的数量
int currentNumberE = 0;
// 外层循环一次, 即把所有剩余香蕉移动一个位置
while (location < distance && currentNumberS > eatNum) {
System.out.println("\n-----当前所在位置--" + location + "--有--" + currentNumberS + "--个香蕉");
// 内层循环是移动一个位置的细节, 可能往返移动多次
while (true) {
if (currentNumberS > maxNum) {
moveOnePosition(location, location + 1, maxNum, eatNum);
currentNumberS -= maxNum;
currentNumberE += maxNum - eatNum;
} else {
moveOnePosition(location, location + 1, currentNumberS, eatNum);
currentNumberE += currentNumberS - eatNum;
currentNumberS = 0;
}
// 看需不需要搬起点剩下的, 即需不需要返回
if (currentNumberS >= eatNum * 2) {
moveOnePosition(location + 1, location, -1, eatNum);
currentNumberE -= eatNum;
} else {
break;
}
}
currentNumberS = currentNumberE;
currentNumberE = 0;
location++;
}
System.out.println("\n搬运完成. 剩余--" + currentNumberS + "--个");
return currentNumberS;
}
/**
* 打印移动一个位置的细节
*
* @param from 起始位置
* @param to 目标位置
* @param number 搬的数量, -1代表不搬, 即往回走
* @param eatNum 搬一米吃的数量
*/
private void moveOnePosition(int from, int to, int number, int eatNum) {
if (number != -1) {
System.out.println("从 " + from + " 位置搬 " + number + " 个到 " + to + " 位置, 消耗" + eatNum + "个");
} else {
System.out.println(" (返)从 " + from + " 位置回到 " + to + " 位置, 消耗 " + eatNum + "个");
}
}
}
测试类:
/**
* 测试类
*
* @author song
*/
public class MonkeysMoveBananasTest {
private static MonkeysMoveBananas monkeysMoveBananas = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
monkeysMoveBananas = new MonkeysMoveBananasImpl();
}
@Test
public void moveTest() {
int k = monkeysMoveBananas.move(100, 50, 50, 1);
assertEquals(k, 16);
//k = monkeysMoveBananas.move(1000, 50, 50, 2);
//assertEquals(k, 20);
}
}