算法-猴子运香蕉,看谁剩的多,N种解法
Posted 香菜聊游戏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法-猴子运香蕉,看谁剩的多,N种解法相关的知识,希望对你有一定的参考价值。
一个猴子身带100个香蕉,他距离家50米。这个猴子要带香蕉回去,但是他一次最多只能背50个香蕉,而且,每走一米他就要吃掉一个香蕉(往 回走也要吃香蕉)。这个猴子最后最多可以带多少个香蕉到家??
第一种解法
package monkey
import "fmt"
var bagSize_ int
var roadLength_ int
var totalBanana_ int
var costPerStep_ int
func Play(roadLength int, bagSize int, totalBanana int, costPerStep int)
bagSize_ = bagSize
roadLength_ = roadLength
totalBanana_ = totalBanana
costPerStep_ = costPerStep
//初始化道路
road = make([]int, roadLength + 1)
road[0] = totalBanana
monkey_ := monkey
defer func()
if err := recover(); err != nil
fmt.Println(err)
fmt.Println(monkey_)
fmt.Println(road)
()
move(&monkey_)
fmt.Println("road info: ", road)
fmt.Println("banan at home: ", road[roadLength])
func move(monkey *monkey)
monkey.release()
fmt.Println("road map >>> ", road)
if monkey.shouldBack()
monkey.back()
else
if(monkey.position == roadLength_)
//猴子到家
return
monkey.pickUp()
monkey.forward()
move(monkey)
var road []int
type monkey struct
position int
bag int
//拾起
func (monkey *monkey) pickUp()
here := road[monkey.position]
if here <= 0
return
pickUpCount := here - monkey.bag
if (pickUpCount + monkey.bag) > bagSize_
pickUpCount = bagSize_ - monkey.bag
//填充猴子背包
monkey.bag = monkey.bag + pickUpCount
//扣减路上的香蕉
road[monkey.position] = here - pickUpCount
//放下香蕉
func (monkey *monkey) release()
road[monkey.position] = road[monkey.position] + monkey.bag
monkey.bag = 0
//前进
func (monkey *monkey) forward()
cost := 1*costPerStep_
monkey.bag = monkey.bag - cost
monkey.position = monkey.position + cost
if monkey.bag < 0
panic("no enough banana to home, die ...")
//后退
func (monkey *monkey) back()
cost := 1*costPerStep_
//退回之前如果背包里没有香蕉,先补充一个
if monkey.bag < cost
monkey.bag = cost
road[monkey.position] = road[monkey.position] - cost
monkey.bag = monkey.bag - cost
monkey.position = monkey.position - cost
//应该后退吗
func (monkey *monkey) shouldBack() bool
//前面还有多少
if monkey.position == 0
return false
left := road[monkey.position - 1]
//最多可以拾起数量
var canPick int
if left >= bagSize_
canPick = bagSize_
else
canPick = left
//退一步拾起,耗费两个香蕉
profits := canPick - 2*costPerStep_
return profits > 0
第二种解法
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 + "个");
第三种解法
public class recursion
private static Monkey monkey = new Monkey();
// 需要搬运的香蕉
static final int TOTAL_BANANA = 3000;
// 路途漫漫
static final int DISTANCE = 1000;
// 猴子能搬运的容量
private static final int POWER = 1000;
// 小笔记本
static LinkedList<Integer[]> NOTE = new LinkedList();
public static void main(String args[])
int remainBanana = getBanana(TOTAL_BANANA, 0, 0.00F);
System.out.println("运输路线如下");
for (Integer integ[] : NOTE)
System.out.printf("%d 米可用 %d 个香蕉,丢弃 %d 个香蕉", integ[0], integ[1], integ[2]);
System.out.print("========");
System.out.printf("最后剩下了:%d 个香蕉", remainBanana);
System.out.println();
static int getBanana(int bananaNum, int position, float rate)
// 香蕉数不够到达目的地
if (bananaNum < DISTANCE)
Integer recode[] = position, bananaNum;
NOTE.add(recode);
return -1;
int remainingBanana = bananaNum % POWER;
int copies = bananaNum / POWER + (remainingBanana > 0 ? 1 : 0);
int carryTimes;
// 计算需要来回几次 carryTimes
if (remainingBanana == 0 || remainingBanana > 2)
carryTimes = copies * 2 - 1;
else
carryTimes = (copies - 1) * 2 - 1;
bananaNum = bananaNum - remainingBanana;
// 可以一次运送过去
if ((POWER > DISTANCE - position) && carryTimes == 1)
Integer recode[] = position, bananaNum, remainingBanana;
NOTE.add(recode);
return bananaNum - (DISTANCE - position);
int nextBananaNum = bananaNum - carryTimes;
// 计算斜率,每单位消耗的香蕉数
float nextRate = 1F / (bananaNum - nextBananaNum);
if (nextRate > rate)
Integer recode[] = position, bananaNum, remainingBanana;
NOTE.add(recode);
return getBanana(nextBananaNum, position + 1, nextRate);
第四种解法
public class Test
// 总数
private static int total = 100;
// 单次运送最大数
private static int max = 50;
// 总距离
private static int length = 50;
// 每次消耗
private static int per = 1;
// 最大值
private static int mod = -1;
public static void main(String[] args)
if (length * per > max || length * per > total)
System.out.println("无法完成");
return;
count(length, total);
System.out.println(mod);
private static void count(int length, int total)
// 最后多次完成
if (length == 0)
if (total > mod)
mod = total;
return;
// 最后一次完成
if (max > total && max > length * per)
if ((total - length * per) > mod)
mod = total - length * per;
return;
// i单次到达距离
for (int i = length; i > 0; i--)
if (total - i * per > 0 && 2 * per * i > max)
continue;
int times;
if (total % max == 0)
times = (total / max - 1) * 2 + 1;
else
if (total % max > 2 * per * i)
times = (total / max) * 2 + 1;
else
// 最后一次剩余不够消耗则丢弃
times = (total / max - 1) * 2 + 1;
total = total - total % max;
int mod = total - times * i * per;
if (mod < (length - i) * per)
return;
count(length - i, mod);
第五种解法
## 无路径版本
``` java
public class MonkeyMoveBanana2
public static void main(String[] args)
int lastLeave = move(1000, 50, 50, 2);
System.out.println("最后剩余:" + lastLeave);
/**
* @param num 香蕉总数
* @param length 距离
* @param max 最大搬运量
* @param per 每米消耗数
*/
static int move(int num, int length, int max, int per)
for (int i = 0; i < length; i++)
if (num < length - i)
num = -1;
break;
if (num <= max)
num = num - (length - i);
break;
int n = num / max;
int lastNum = num % max;
if (lastNum > 2 * per)
n = num / max + 1;
else
num -= lastNum;
num -= (per + (n - 1) * 2 * per);
if (num < 0)
num = -1;
return num;
```
## 有路径信息版本
``` java
public class MonkeyMoveBanana3
public static void main(String[] args)
int lastLeave = move(1000, 50, 50, 1);
if (lastLeave >= 0)
System.out.println("最后剩余:" + lastLeave);
static Map<Integer, Integer> numInPos = new LinkedHashMap<>();
/**
* @param num 香蕉总数
* @param length 距离
* @param max 最大搬运量
* @param per 每米消耗数
*/
static int move(int num, int length, int max, int per)
numInPos.put(0, num);
for (int i = 0; i < length; i++)
if (num < length - i)
num = -1;
break;
if (num <= max)
go(i, length - i, per, num);
num = num - (length - i);
break;
int n = num / max;
int lastNum = num % max;
if (lastNum > 2 * per)
n = num / max + 1;
else
num -= lastNum;
lastNum = 0;
num -= (per + (n - 1) * 2 * per);
goMetre(i, per, max, n, lastNum);
if (num < 0)
num = -1;
System.out.println("monkey die");
return num;
static void goMetre(int pos, int per, int max, int n, int lastMove)
for (int i = 0; i < n - 1; i++)
go(pos, 1, per, max);
back(pos + 1, 1, per, 1);
if (lastMove == 0)
go(pos, 1, per, max);
else
go(pos, 1, per, lastMove);
/**
* 向前走
*
* @param pos 起点
* @param distance 前进距离
* @param per 每米消耗
* @param payload 起点携带数量
*/
static void go(int pos, int distance, int per, int payload)
int newPos = pos + distance;
int cost = distance * per;
int surplus = payload - cost;
for (int i = 0; i < pos; i++)
System.out.print(" ");
for (int i = 0; i < distance; i++)
System.out.print(">");
if (!numInPos.containsKey(newPos))
numInPos.put(newPos, 0);
numInPos.put(pos, numInPos.get(pos) - payload);
numInPos.put(newPos, numInPos.get(newPos) + surplus);
System.out.format("\\t [%d->%d] 带%d个,进%d米,吃%d个,剩%d个。\\t", pos, newPos, payload, distance, cost, surplus);
printNumInPos();
/**
* 往回走
*
* @param pos 起点
* @param distance 前进距离
* @param per 每米消耗
* @param payload 起点携带数量
*/
static void back(int pos, int distance, int per, int payload)
int newPos = pos - distance;
int cost = distance * per;
int surplus = payload - cost;
for (int i = 0; i < newPos; i++)
System.out.print(" ");
for (int i = 0; i < distance; i++)
System.out.print("<");
numInPos.put(pos, numInPos.get(pos) - payload);
numInPos.put(newPos, numInPos.get(newPos) + surplus);
System.out.format("\\t [%d<-%d] 带%d个,退%d米,吃%d个,剩%d个。\\t", newPos, pos, payload, distance, cost, surplus);
printNumInPos();
static void printNumInPos()
for (Integer key : numInPos.keySet())
if (numInPos.get(key) != 0)
System.out.format("pos[%d]=%d\\t", key, numInPos.get(key));
System.out.println();
```
第六种
第一种:
package com.example.sbpracdemo.houzi;
public class Test3
public static void main(String[] args)
int bananaNum = 100;//香蕉总数量 150
int carryBanana = 50;//能运多少香蕉
int distance = 50; //距离家多远1
int remainingTotalAmount = bananaNum;//剩余香蕉总数量
//搬不走的香蕉数量
int notCarryBanana = bananaNum - carryBanana;
//搬走香蕉的剩余数量
int remainingCarryBanana = carryBanana;
//搬走香蕉
int carryNum = carryBanana;
for (int i = 1; i <= distance; i++)
System.out.print("走" + i + "米,搬走香蕉" + carryNum);
remainingCarryBanana--;//走一米要吃掉一个香蕉
remainingTotalAmount = remainingCarryBanana + notCarryBanana;
System.out.println(",搬走香蕉的剩余数量:" + remainingCarryBanana + ",搬不走的香蕉数量:" + notCarryBanana + ",剩余香蕉总数量:" + remainingTotalAmount);
//如果剩余数量小于等于能拖的数量,直接回家
if(remainingTotalAmount<=carryBanana)
carryNum = remainingCarryBanana;
notCarryBanana = 0;
continue;
//香蕉剩余数量要能够走回家
if(remainingTotalAmount>(distance-i))
int temp = (int) Math.ceil((double) notCarryBanana / (double) carryBanana);
if (temp > 1)
int ss=notCarryBanana;
for (int j = 0; j < temp; j++)
carryNum = carryBanana;
if(j==temp-1)
carryNum=ss-carryBanana*(temp-1);
//回去要吃掉一个香蕉
remainingCarryBanana--;
//背在原地的香蕉
notCarryBanana--; //49
remainingTotalAmount = remainingCarryBanana + notCarryBanana;
if (remainingTotalAmount > carryBanana)
notCarryBanana = remainingTotalAmount - carryBanana;
remainingCarryBanana = remainingTotalAmount - notCarryBanana;
else
remainingCarryBanana = remainingTotalAmount;
notCarryBanana = 0;
System.out.println("回走,搬走香蕉" + carryNum + ",剩余香蕉总数量:" + remainingTotalAmount);
else
if (notCarryBanana != 0)
carryNum = notCarryBanana;
remainingCarryBanana--;//回去要吃掉一个香蕉 48
//背在原地的香蕉
notCarryBanana--; //49
remainingTotalAmount = remainingCarryBanana + notCarryBanana;
if (remainingTotalAmount > carryBanana)
notCarryBanana = remainingTotalAmount - carryBanana;
remainingCarryBanana = remainingTotalAmount - notCarryBanana;
else
remainingCarryBanana = remainingTotalAmount;
notCarryBanana = 0;
System.out.println("回走,搬走香蕉" + carryNum + ",剩余香蕉总数量:" + remainingTotalAmount);
carryNum = remainingCarryBanana;
System.out.println("猴子最后最多可以带" + remainingTotalAmount + "个香蕉到家");
第二种
package com.example.sbpracdemo.houzi;
/**
* 密级别:classify:p2#- User: Jinlili Date: 2018/8/2322:46 Description:
*/
public class Test2
public static void main(String[] args)
System.out.println(walk(100, 50, 50));
/**
* @param bananaNum 总共多少根
* @param carryBanana 每次拖多少根
* @param distance 离家多少米
*/
public static int walk(int bananaNum, int carryBanana, int distance)
int[] gj = new int[distance + 1];
for (int i = 1; i <= distance; i++)
gj[i] = bananaNum;
bananaNum = bananaNum - ((int) Math.ceil((double) bananaNum / (double) carryBanana) * 2 - 1);
if (bananaNum < 0)
bananaNum = 0;
System.out.println("不可达");
break;
return bananaNum;
以上是关于算法-猴子运香蕉,看谁剩的多,N种解法的主要内容,如果未能解决你的问题,请参考以下文章