shopee的零食柜-动态规划-校招编程真题

题目描述

shopee的零食柜,有着各式各样的零食,但是因为贪吃,小虾同学体重日益增加,终于被人叫为小胖了,他终于下定决心减肥了,他决定每天晚上去操场跑两圈,但是跑步太累人了,他想转移注意力,忘记痛苦,正在听着音乐的他,突然有个想法,他想跟着音乐的节奏来跑步,音乐有7种音符,对应的是1到7,那么他对应的步长就可以是1-7分米,这样的话他就可以转移注意力了,但是他想保持自己跑步的速度,在规定时间m分钟跑完。为了避免被累死,他需要规划他每分钟需要跑过的音符,这些音符的步长总和要尽量小。下面是小虾同学听的歌曲的音符,以及规定的时间,你能告诉他每分钟他应该跑多少步长?

输入描述

输入的第一行输入 n(1 ≤ n ≤ 1000000,表示音符数),m(1<=m< 1000000, m <= n)组成,

第二行有 n 个数,表示每个音符(1<= f <= 7)

输出描述

输出每分钟应该跑的步长

示例

输入

8 5
6 5 6 7 6 6 3 1

输出

11

问题分析

这道题直观地理解:输入一个数组(一组音符数)nums[n],按相邻数字和的最小值合并相邻数字,直到数字个数等于m,输出最大的数。比如示例输入:最后合并得到的数组是 11 6 7 6 10 (3 1 先合并相加为4,4 6 再合并相加为10,6 5合并相加为11)。

如果按照这个直观的理解编写算法,算法的复杂度会很大,不满足题意。事实上,可以用动态规划的方法分析。

动态规划:输入音符数,最少也要1分钟跑完这些音符数,即 一分钟跑 数组nums[n]的和 sum 步;(可以理解为子问题是连续序列求和值)
2分钟跑完,最大步数steps为数组nums的对半求和值;
判断按照当前最大步数steps跑,需要跑多少分钟times,若times大于m(跑得太慢),说明当前最大步数steps太小了,需要增大最大步数;若times小于m(跑得太快),说明当前最大步数steps太大了,需要减小步数。 并对steps按对半求和计算,继续判断。
按照这样判断,逐步+1或-1,即可求出解。

package test;

import java.io.IOException;
import java.util.Scanner;

public class ShopT{
    public static int timeCheck(int[] a,int step){
        int time=1;//最少也要一分钟
        int sum=0;//前k步步数总和
        for(int i:a){
            if(sum+i>step){//前k步步数和大于step(最大步数)
                sum=i;
                time+=1;
            }else{
                sum+=i;
            }
        }
        return time;
    }
    public static void main(String args[]) throws IOException{
        Scanner bf=new Scanner(System.in);
        int max=0;
        int sum=0;
        int steps=0;
        int times=0;
        int n=bf.nextInt();
        int m=bf.nextInt();
        int a[]=new int[n];
        for(int i=0;i<n;i++){
            a[i]=bf.nextInt();
            max=Math.max(max,a[i]);
            sum+=a[i];
        }
        while(max<sum){
            steps=max+(sum-max)/2;
            times=timeCheck(a,steps);
            if(times>m){//花费时间大于规定时间 m,故最大步数要增大
                max=steps+1;
            }else if(times<m){//花费时间小于规定时间 m,故最大步数要减少
                sum=steps-1;
            }else{
                sum=steps;
            }
        }
        System.out.println(max);
        bf.close();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值