华为OD机考算法题:食堂供餐

目录

题目部分

解析与思路

代码实现


题目部分

题目 食堂供餐
题目说明 某公司员工食堂以盒饭方式供餐。为将员工取餐排队时间降低为0,食堂的供餐速度必须要足够快。现在需要根据以往员工取餐的统计信息,计算出一个刚好能达成排队时间为0的最低供餐速度。即,食堂在每个单位时间内必须至少做出多少份盒饭才能满足要求。
输入描述 第1行为一个正整数N,表示食堂开餐时长。1 <= N <= 1000。
第2行为一个正整数M,表示开餐前食堂已经准备好的盒饭份数。pi <= M <= 1000。
第3行为N个正整数,用空格分隔,依次表示开餐时间内按时间顺序每个单位时间进入食堂取餐的人数Pi。1 <=i<= N,0<= Pi<=100。
输出描述 一个整数,能满足题目要求的最低供餐速度(每个单位时间需要做出多少份盒饭)。
补充说明 每人只取一份盒饭。
需要满足排队时间为0,必须保证取餐员工到达食堂时,食堂库存盒饭数量不少于本次来取餐的人数。
第一个单位时间来取餐的员工只能取开餐前食堂准备好的盒饭。
每个单位时间里制作的盒饭只能供应给后续单位时间来的取餐的员工。
食堂在每个单位时间里制作的盒饭数量是相同的。
------------------------------------------
示例
示例1
输入 3
14
10 4 5
输出 3
说明 本样例中,总共有3批员工就餐,每批人数分别为10、4、5。
开餐前食堂库存14份。
 
食堂每个个单位时间至少要做出3份餐饭才能达成排队时间为0的目标。具体情况如下:
第一个单位时间来的10位员工直接从库存取餐。取餐后库存剩余4份盒饭,加上第一个单位时间做出的3份,库存有7份。
第二个单位时间来的4员工从库存的7份中取4份。取餐后库存剩余3份盒饭,加上第二个单位时间做出的3份,库存有6份。
第三个单位时间来的员工从库存的6份中取5份,库存足够。
  
如果食堂在单位时间只能做出2份餐饭,则情况如下:
第一个单位时间来的10位员工直接从库存取餐。取餐后库存剩余4份盒饭,加上第一个单位时间做出的2份,库存有6份。
第二个单位时间来的4员工从库存的6份中取4份。取餐后库存剩余2份盒饭,加上第二个单位时间做出的2份,库存有4份。
第三个单位时间来的员工需要取5份,但库存只有4份,库存不够。

解析与思路

题目解读

此题中,第1行是就餐员工的总批数,设为 count;第2行是初始库存数,设为 stockQty;第3行是每批次的份数,假设每批次的数字放到数组 dinners 中,那么dinners的长度为count,且dinners[i] 即为第 ( i + 1 ) 个批次所需的份数(备注:批次起始值为1,放到数组的第 0 个元素)。

假设题目中最低的供餐速度为 x(x为正整数),那么 对于所有的 i ( 0 <= i <= count),x 必须满足 ( stockQty + x * i) >=  \sum_{idx=0}^{i} dinners[idx]。其中, \sum_{idx=0}^{i} dinners[idx] 代表着dinners数组的前 i 个元素之和,即 \sum_{idx=0}^{i} dinners[idx] = dinners[0] + dinners[1] + … + dinners[i]。

分析思路

设置 x 的初始值为0。

根据不等式 ( stockQty + x * i) >=  \sum_{idx=0}^{i} dinners[idx],对于 i, 从 0 到 ( count -1 ) ,判断当前的 x 值是否保证不等式成立:

  • 如果不等式成立,则不进行任何操作;
  • 如果不等式不成立,即 x 值过小,重新计算 x 的值。x 的新值必定比老值更大。
    我们知道,当 从 0 到 ( i - 1 ), x 的老值都能保证不等式成立,现在 x 的值变大了,不等式的左边比以前更大。这意味着这个不等式对于 x 的新值在 0 到 ( i - 1 )  一定是成立的。

最终计算出的 x 即是题目要求的值。

此算法只需要遍历一次 dinners 数组,时间复杂度为 o(n);由于使用了辅助数组,其空间复杂度也为o(n)。


代码实现

Java代码

import java.util.Scanner;

/**
 * 食堂供餐
 * @since 2023.09.05
 * @version 0.1
 * @author Frank
 *
 */
public class Dinners {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		// 第一行输入就餐的批次
		String strCount = sc.nextLine();
		int count = Integer.parseInt( strCount );
		
		// 第二行输入初始库存数
		String strStockQty = sc.nextLine();
		int stockQty = Integer.parseInt( strStockQty );
		
		// 第三行输入每批次所需的午餐份数
		// 此处dinners中的元素都是String,后面需要转换成int处理
		String strDinners = sc.nextLine();
		String[] dinners = strDinners.split(" "); // dinners.length == count
				
		int currentSumNeeded = 0;
		int x = 0;
		int currentStock = stockQty;
		for( int i = 0; i < count; i ++ )
		{
			currentStock = stockQty + i * x;
			currentSumNeeded += Integer.parseInt( dinners[i] );	
			if( currentStock < currentSumNeeded )
			{
				// 计算最小的 x(新值必定比当前的x大),确保 currentStock >= currentSumNeeded
				int diff = currentSumNeeded - stockQty;
				int tmpX =  diff / i;
				if( diff % i != 0 )
				{
					tmpX ++;
				}
				x = tmpX;
			}
		}
		System.out.println( x );
	}
}

JavaScript代码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
    let input = [];
    while (line = await readline()) {
        input.push(line);
    }

    // 第一行,进餐的批次
    var strCount = input[0];
    var count = parseInt(strCount);

    // 第二行,初始库存数
    var strStockQty = input[1];
    var stockQty = parseInt(strStockQty);

    // 第三行,每批次需要的份数
    var strDinners = input[2].split(" ");

    var currentSumNeeded = 0;
    var x = 0;
    var currentStock = stockQty;
    for (var i = 0; i < count; i++) {
        currentStock = stockQty + i * x;
        currentSumNeeded += parseInt(strDinners[i]);
        if (currentStock < currentSumNeeded) {
            // 计算最小的 x(新值必定比当前的x大),确保 currentStock >= currentSumNeeded
            var diff = currentSumNeeded - stockQty;
            var tmpX = parseInt(diff / i);
            if (diff % i != 0) {
                tmpX++;
            }
            x = tmpX;
        }
    }
    console.log(x);
}();

(完)

你可能感兴趣的:(华为OD机考,算法,华为OD,Java,JavaScript,数据结构)