2024蓝桥杯真题——食堂(2024省赛真题,学会多10分!!!)

目录

题目链接:4.食堂 - 蓝桥云课

题目描述

输入格式

输出格式

样例输入

样例输出

样例说明

评测用例规模与约定

解法一:贪心,能解决的好方法

比赛时候我的答案

方法思路

Java写法:

C++写法:

AC情况

时间复杂度和空间复杂度

空间复杂度分析

总结



题目链接:4.食堂 - 蓝桥云课

注:下述题目描述和示例均来自蓝桥云客

题目描述

S 学校里一共有 a2 个两人寝、a3​ 个三人寝,a4​ 个四人寝,而食堂里有 b4​ 个四人桌和 b6​ 个六人桌。学校想要安排学生们在食堂用餐,并且满足每个寝室里的同学都在同一桌就坐,请问这个食堂最多同时满足多少同学用餐?

输入格式

采用多组数据输入。

输入共 q+1 行。

第一行为一个正整数 q 表示数据组数。

后面 q 行,每行五个非负整数 a2,a3,a4,b4,b6​ 表示一组数据。

输出格式

输出共 q 行,每行一个整数表示对应输入数据的答案。

样例输入

2
3 0 1 0 1
0 2 2 1 1

样例输出

6
10

样例说明

对于第一组数据,只有一个六人桌,因此最多安排三个两人寝的同学就餐,答案为 (2+2+2)=6 。

对于第二组数据,用一个六人桌安排两个三人寝的同学,用一个四人桌安排一个四人寝的同学,答案为 (3+3)+(4)=10( 。

评测用例规模与约定

对于 20%20% 的评测用例,保证 a2+a3+a4≤8 。

对于 100%100% 的评测用例,保证 q≤100,b4+b6≤a2+a3+a4≤100。


解法一:贪心,能解决的好方法

比赛时候我的答案

import java.util.Scanner;

public class DiningArrangementFixed {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        int q = scanner.nextInt();
        
        while(q-- > 0){

          int a2 = scanner.nextInt();
          int a3 = scanner.nextInt();
          int a4 = scanner.nextInt();
          
          int b4 = scanner.nextInt();
          int b6 = scanner.nextInt();

          int res = 0;

          // 1.先看3+3的
          while(a3 >= 2 && b6 >= 1){
            a3 -= 2;
            b6--;
            res += 6;
          }

          // 2.看4+2的
          while(a4 >= 1 && a2 >= 1 && b6 >= 1){
            a4--;
            b6--;
            res += 6;
          }

          // 3.看单独一个4的
          while(a4 >= 1 && b4 >= 1){
            a4--;
            b4--;
            res += 4;
          }

          // 4.看2+2+2的
          while(a2 >= 3 && b6 >= 1){
            a2 -= 3;
            b6--;
            res += 6;
          }

          // 5.看2+2的
          while(a2 >= 2 && b4 >= 1){
            a2 -= 2;
            b4--;
            res += 4;
          }



          // -------------上述都是满配的情况-------------
          // -------------下面展示不满配的情况-------------
          // 1.看b6放3+2的
          while(a3 >= 1 && a2 >= 1 && b6 >= 1){
            a3--;
            a2--;
            b6--;
            res += 5;
          }

          // 5.看b4放3的
          while(a3 >= 1 && b4 >= 1){
            a3--;
            b4--;
            res += 3;
          }

          // 2.看b6放4的
          while(a4 >= 1 && b6 >= 1){
            a4--;
            b6--;
            res += 4;
          }
          // 3.看b6放3的
          while(a3 >= 1 && b6 >= 1){
            a3--;
            b6--;
            res += 3;
          }
          // 4.看b6放2的
          while(a2 >= 1 && b6 >= 1){
            a2--;
            b6--;
            res += 2;
          }



          // 5.看b4放2的
          while(a2 >= 1 && b4 >= 1){
            a2--;
            b4--;
            res += 2;
          }

          System.out.println(res);
        }

        scanner.close();
    }
}

最后的效果也不是很好但是也是拿到一点分数

于是我就思考我到底哪里错了。(最后发现是个很小的错误┭┮﹏┭┮)

我重新想了想,我们的大体思路没有改变,还是先满配,再放空余的。

方法思路

  1. 处理四人桌:优先安排四人寝,然后是两个两人寝的组合,接着是三人寝,最后是单人两人寝。

  2. 处理六人桌:优先安排两个三人寝,然后是四人寝和两人寝的组合,接着是三个两人寝,之后是四人寝,然后是三人寝和两人寝的组合,最后处理剩余的两人寝和三人寝。

其实中间有很多的顺序都是可以换的,但是2+2+2一定要在2+2之前


Java写法:

import java.util.Scanner;

public class DiningArrangementFixed {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        int q = scanner.nextInt();
        
        while(q-- > 0){

          int a2 = scanner.nextInt();
          int a3 = scanner.nextInt();
          int a4 = scanner.nextInt();
          
          int b4 = scanner.nextInt();
          int b6 = scanner.nextInt();

          int res = 0;

          // 1.先看3+3的
          while(a3 >= 2 && b6 >= 1){
            a3 -= 2;
            b6--;
            res += 6;
          }

          // 2.看4+2的
          while(a4 >= 1 && a2 >= 1 && b6 >= 1){
            a4--;
            a2--;
            b6--;
            res += 6;
          }

          // 3.看单独一个4的
          while(a4 >= 1 && b4 >= 1){
            a4--;
            b4--;
            res += 4;
          }

          // 4.看2+2+2的
          while(a2 >= 3 && b6 >= 1){
            a2 -= 3;
            b6--;
            res += 6;
          }

          // 5.看2+2的
          while(a2 >= 2 && b4 >= 1){
            a2 -= 2;
            b4--;
            res += 4;
          }



          // -------------上述都是满配的情况-------------
          // -------------下面展示不满配的情况-------------
          // 1.看b6放3+2的
          while(a3 >= 1 && a2 >= 1 && b6 >= 1){
            a3--;
            a2--;
            b6--;
            res += 5;
          }

          // 5.看b4放3的
          while(a3 >= 1 && b4 >= 1){
            a3--;
            b4--;
            res += 3;
          }

          // 2.看b6放4的
          while(a4 >= 1 && b6 >= 1){
            a4--;
            b6--;
            res += 4;
          }
          // 3.看b6放3的
          while(a3 >= 1 && b6 >= 1){
            a3--;
            b6--;
            res += 3;
          }
          // 4.看b6放2的
          while(a2 >= 1 && b6 >= 1){
            a2--;
            b6--;
            res += 2;
          }



          // 5.看b4放2的
          while(a2 >= 1 && b4 >= 1){
            a2--;
            b4--;
            res += 2;
          }

          System.out.println(res);
        }

        scanner.close();
    }
}

C++写法:

#include <iostream>

int main() {
    int q;
    std::cin >> q;

    while(q-- > 0) {
        int a2, a3, a4, b4, b6;
        std::cin >> a2 >> a3 >> a4 >> b4 >> b6;

        int res = 0;

        // 1. 先看3+3的
        while(a3 >= 2 && b6 >= 1) {
            a3 -= 2;
            --b6;
            res += 6;
        }

        // 2. 看4+2的
        while(a4 >= 1 && a2 >= 1 && b6 >= 1) {
            --a4;
            --a2;
            --b6;
            res += 6;
        }

        // 3. 看单独一个4的
        while(a4 >= 1 && b4 >= 1) {
            --a4;
            --b4;
            res += 4;
        }

        // 4. 看2+2+2的
        while(a2 >= 3 && b6 >= 1) {
            a2 -= 3;
            --b6;
            res += 6;
        }

        // 5. 看2+2的
        while(a2 >= 2 && b4 >= 1) {
            a2 -= 2;
            --b4;
            res += 4;
        }

        // -------------上述都是满配的情况-------------
        // -------------下面展示不满配的情况-------------

        // 1. 看b6放3+2的
        while(a3 >= 1 && a2 >= 1 && b6 >= 1) {
            --a3;
            --a2;
            --b6;
            res += 5;
        }

        // 2. 看b4放3的
        while(a3 >= 1 && b4 >= 1) {
            --a3;
            --b4;
            res += 3;
        }

        // 3. 看b6放4的
        while(a4 >= 1 && b6 >= 1) {
            --a4;
            --b6;
            res += 4;
        }

        // 4. 看b6放3的
        while(a3 >= 1 && b6 >= 1) {
            --a3;
            --b6;
            res += 3;
        }

        // 5. 看b6放2的
        while(a2 >= 1 && b6 >= 1) {
            --a2;
            --b6;
            res += 2;
        }

        // 6. 看b4放2的
        while(a2 >= 1 && b4 >= 1) {
            --a2;
            --b4;
            res += 2;
        }

        std::cout << res << std::endl;
    }

    return 0;
}

AC情况

时间复杂度和空间复杂度

        该算法的时间复杂度主要取决于输入数据的规模以及内部循环执行的次数。对于每个测试用例(由外部while(q-- > 0)循环控制),算法通过一系列的while循环来计算结果。这些内部循环的执行次数依赖于输入值a2, a3, a4, b4, 和 b6

  • 每个内部while循环最多执行次数与对应变量的初始值成正比。例如,处理a3 >= 2 && b6 >= 1条件的循环最多执行min(a3/2, b6)次。
  • 因为每次循环都会减少至少一个相关变量的数量,并且这些变量的总数量是有限的(即它们的初始值),所以可以认为每个内部循环在最坏情况下的时间复杂度与这些变量的最大值成线性关系。

因此,对于每个单独的测试用例,算法的时间复杂度大致为O(n),其中n是所有输入参数(a2, a3, a4, b4, b6)最大值的一个函数。如果考虑q个测试用例的整体影响,则总时间复杂度为O(q * n)。

空间复杂度分析

空间复杂度主要关注算法运行过程中所需的额外存储空间。在这个程序中:

  • 只使用了几个整型变量(a2a3a4b4b6res)来存储输入和中间结果。
  • 不论输入大小如何,使用的额外空间量保持不变。

        因此,该算法的空间复杂度为O(1),即常数级别的空间复杂度。这意味着它不需要随输入大小增加而增加额外的内存空间,除了用于接收输入的那些固定数量的变量之外。

        总结:此算法具有线性时间复杂度O(q * n)和常数空间复杂度O(1),这里的n指的是单个测试用例中输入参数的最大值。这种特性使得该算法非常适合处理相对较小规模的输入数据集。




总结

        我怎么说呢,这个贪心其实是一个很简单的题目,但是临场发挥的时候就是发挥不出来,我真的服了铁铁。好像我只会暴力求解。┭┮﹏┭┮

### 蓝桥杯 Java 比中的食堂问题析 在蓝桥杯中,涉及食堂场景的问题通常会围绕排队、资源配以及优化路径等方面展开。这类题目旨在考察参者的逻辑思维能力和算法设计能力。 对于食堂相关问题,可以考虑如下方面: - **排队模型**:模拟学生进入食堂就餐的过程,计算等待时间或者最优服务顺序等问题。此类问题可能涉及到优先级队列的应用[^2]。 - **资源配**:假设食堂种菜品窗口开放,不同窗口的服务速度不一样,如何安排使得总体满意度最高或平均等待最短等目标函数下的最佳策略求解。 - **路径规划**:当食堂布局较为复杂时,可能会出现寻找从入口到达指定位置(比如某个特定窗口)的最佳路线问题,这可以通过图论中的最短路算法实现。 针对上述提到的使用`Map`存储并处理数据的方法[^4],可以在解决某些具体类型的食堂问题时提供有效的解决方案框架。例如,在统计各个打饭队伍的人数布状况时,利用键值对的形式记录每条队列编号及其对应人数,并通过对这些数值排序找出当前人数最少的那个队列为新到来的同学推荐加入。 然而需要注意的是,实际竞中遇到的具体题目往往更加灵活变,因此除了掌握基础的数据结构外还需要具备良好的编程技巧和创新意识来应对各种挑战。 ```java // 示例代码片段展示了一个简单的基于HashMap统计各队列长度的功能 import java.util.*; public class CanteenQueue { public static void main(String[] args){ Map<Integer, Integer> queueLengths = new HashMap<>(); // 假设这里已经获取到了所有队列的信息... // 更新queueLengths map List<Map.Entry<Integer,Integer>> list = new ArrayList<>(queueLengths.entrySet()); Collections.sort(list,(o1,o2)->(o1.getValue()).compareTo(o2.getValue())); System.out.println("建议前往:" + list.get(0).getKey() +"号窗口"); } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值