算法-猴子搬香蕉

问题描述:  

 

 一个小猴子边上有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);
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值