最少需要准备多少香蕉,能保证所有猴子都能吃饱

题目描述

动物园有猴山,每天需要给猴子们发香蕉,猴子会排队依次取食。猴子们铺张浪费,会多拿食物,但最多不会拿超过自身食量的二倍且不会超过当前还存在的香蕉的一半,最后—个猴子除外(即最后—个猴子可以拿完剩余的所有香蕉)。
最少需要准备多少香蕉,能保证所有猴子都能吃饱?

解题思路

先考虑只有一个猴子的情况,那么最少需要的香蕉数量即为这个猴子的食量

如果有3个猴子,那么先让第一个猴子拿香蕉,假设它的食量为4,它最多可能拿8个香蕉,最少可能拿4个香蕉,因为题目是要求最少需要准备多少香蕉,我们假设这个猴子知足常乐,只拿了4个香蕉,但是又有要求猴子拿的香蕉不会超过当前还存在的香蕉的一半,那么我们就给它准备8个香蕉,它只拿 了4个,还剩下4个

接下来喂第二个猴子,如果它的食量为3,那么它只拿3个就能吃饱了,但是拿了3个之后就只剩下1个香蕉了,不满足猴子拿的香蕉不会超过当前还存在的香蕉的一半,那么我们在喂第2个猴子的时候就再加入2个香蕉就可以了,假设它也知足常乐,现在一共剩6个香蕉,它拿了3个,还剩下3个香蕉

接下来喂第三个猴子,如果它的食量为3或者,那么它只拿3个就能吃饱了,就不用再加香蕉了
那么喂第一个猴子准备了8个香蕉,喂第二个猴子准备了2个香蕉,喂第三个猴子准备了0个香蕉.最少需要准备的香蕉数量为 8+2+0=10

输入:[4,3,3]
输出:10

现在假设第3个猴子的食量为5,但是现在只剩下3个香蕉了,我们再加2个香蕉就可以让它吃饱了
那么喂第一个猴子准备了8个香蕉,喂第二个猴子准备了2个香蕉,喂第三个猴子准备了2个香蕉.最少需要准备的香蕉数量为 8+2+2=12

输入:[4,3,5]
输出:12

总结:我们一个一个地喂猴子,把每一次需要加入的香蕉数量用一个数组存起来,最后把数组元素相加就可以了,同时我们需要用另一个数组记录每一次喂完之后剩余的香蕉数(节约空间,也可以用变量), 当当前猴子的2倍食量小于等于当前剩余的香蕉数时,需要加入的香蕉数量为0,当当前猴子的2倍食量大于当前剩余的香蕉数时,需要加入的香蕉数量为2倍食量减当前剩余的香蕉数量

动态方程式

for (int i = 1; i < arr.length - 1; i++) {
    
    
            if (2*arr[i] <= dp_remain[i-1]) {
    
    
                dp[i] = 0;
                dp_remain[i]=dp_remain[i-1]-arr[i];
            } else {
    
    
                dp[i] = 2 * arr[i] - dp_remain[i-1];
                dp_remain[i]=dp_remain[i-1]+dp[i]-arr[i];
            }
        }

在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

扫描二维码关注公众号,回复: 12885875 查看本文章

代码实现

/**
 * Created by 此生辽阔 on 2021/3/21 10:50
 */
public class Monkey {
    
    
    public static void main(String[] args) {
    
    
       // int []arr={3,5,4,2};
        int []arr={
    
    5,4,6,2,3,1,9};
        solutionMokey solutionMokey = new solutionMokey();
        System.out.println(solutionMokey.minBanana(arr));
    }

}
class solutionMokey{
    
    

    int minBanana(int arr[]) {
    
    
        int[] dp = new int[arr.length];//每一次需要加入的香蕉数量
        int [] dp_remain=new int[arr.length];//每一次喂完剩余的香蕉数量
      if(arr.length==1)//考虑只有一个猴子的情况
      {
    
    
          return arr[0];
      }

        dp[0] = 2 * arr[0];//当有多个猴子,初始化dp
        dp_remain[0]=arr[0];//当有多个猴子,初始化 dp_remain
        for (int i = 1; i < arr.length - 1; i++) {
    
    //计算第2个到第n-1个猴子的投喂情况
            if (2*arr[i] <= dp_remain[i-1]) {
    
    
                dp[i] = 0;
                dp_remain[i]=dp_remain[i-1]-arr[i];
            } else {
    
    
                dp[i] = 2 * arr[i] - dp_remain[i-1];
                dp_remain[i]=dp_remain[i-1]+dp[i]-arr[i];
            }
        }

      if(arr.length-1>=0&&arr.length-2>=0)//考虑数组越界
      {
    
    

        if(arr[arr.length-1]>dp_remain[arr.length-2])//计算最后一个猴子的投喂情况
        {
    
    
            dp[arr.length-1]=arr[arr.length-1]-dp_remain[arr.length-2];
        }
        else
        {
    
    
            dp[arr.length-1]=0;
        }
      }

          int sum=0;
        for(int j=0;j<=dp.length-1;j++)//dp数组求和,计算最少需要投喂的香蕉数量
        {
    
    
           System.out.print(dp[j]+" ");
            sum=sum+dp[j];
        }
        System.out.println();
        return sum;
    }

结果展示

在这里插入图片描述

代码实现2

为了结约空间,每一次需要加入的香蕉数量和每一次喂完剩余的香蕉数量都可以用变量来表示,同时用sum来记录香蕉总数

package nowcoder;

/**
 * Created by 此生辽阔 on 2021/3/21 10:50
 */
public class Monkey {
    
    
    public static void main(String[] args) {
    
    
       // int []arr={3,5,4,2};
        int []arr={
    
    5,4,6,2,3,1,9};
        solutionMokey solutionMokey = new solutionMokey();
        System.out.println(solutionMokey.minBanana(arr));
    }

}
class solutionMokey{
    
    

    int minBanana(int arr[]) {
    
    
        int dp = 0;//每一次需要加入的香蕉数量
        int  dp_remain=0;//每一次喂完剩余的香蕉数量
        int sum=0;//香蕉总数
      if(arr.length==1)//考虑只有一个猴子的情况
      {
    
    
          return arr[0];
      }
        dp = 2 * arr[0];//当有多个猴子,初始化dp
        sum=sum+dp;
       // dp_remain[0]=arr[0];//当有多个猴子,初始化 dp_remain
        dp_remain=arr[0];
        for (int i = 1; i < arr.length - 1; i++) {
    
    //计算第2个到第n-1个猴子的投喂情况
            if (2*arr[i] <= dp_remain) {
    
    
                dp = 0;
                dp_remain=dp_remain-arr[i];
            } else {
    
    
                dp = 2 * arr[i] - dp_remain;
                dp_remain=dp_remain+dp-arr[i];
            }
            sum=sum+dp;
        }

      if(arr.length-1>=0&&arr.length-2>=0)//考虑数组越界
      {
    
    

        if(arr[arr.length-1]>dp_remain)//计算最后一个猴子的投喂情况
        {
    
    
            dp=arr[arr.length-1]-dp_remain;
        }
        else
        {
    
    
            dp=0;
        }
        sum=sum+dp;
      }
        return sum;
    }
}

结果展示

在这里插入图片描述

声明:仅代表我个人的解题思路,我只有题目,没有解题方法和标准答案,不知道我的思路是否正确,本文仅供参考,欢迎在评论区留言交流

猜你喜欢

转载自blog.csdn.net/ningmengshuxiawo/article/details/115047530