星际篮球争霸赛/MVP争夺战 - 华为OD机试真题(A卷、Java题解)

华为OD机试题库《C++》限时优惠 9.9

华为OD机试题库《Python》限时优惠 9.9

华为OD机试题库《JavaScript》限时优惠 9.9

针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)。

看不懂有疑问需要答疑辅导欢迎私VX: code5bug

题目描述

在星球争霸篮球赛对抗赛中,最大的宇宙战队希望每个人都能拿到MVP。

MVP的条件是单场最高分得分获得者,可以并列,所以宇宙战队决定在比赛中尽可能让更多队员上场且让所有得分的选手得分都相同。

然而比赛过程中的每1分钟的得分都只能由某一个人包揽。

输入描述

输入第一行为一个数字t,表示为有得分的分钟数(1<=t<=50)

第二行为t个数字,代表每一分钟的得分p,(1<=p<=50)

输出描述

输出有得分的队员都是MVP时,最少得MVP得分

示例1

复制代码
输入:
9
5 2 1 5 2 1 5 2 1

输出:
6

说明:
样例解释:一共4人得分,分别都为6分
5 + 1
5 + 1
5 + 1
2 + 2 + 2

题解

这道题目属于**回溯算法(Backtracking) 贪心算法(Greedy Algorithm)的结合。我们需要将给定的得分分钟数分配到一个或多个队员中,使得每个队员的总得分相同,并且这个相同的得分尽可能小。这类似于分割等和子集(Partition to K Equal Sum Subsets)**的问题。

解题思路

  1. 问题分析 :我们需要将所有的分钟得分分配给若干个队员,每个队员的总得分相同,且这个得分是所有可能中最小的。这意味着我们需要找到一个得分 score,使得所有分钟得分可以被分成若干组,每组的和恰好是 score,并且 score 是满足条件的最小值。
  2. 关键步骤
    • 计算总和 :首先计算所有分钟得分的总和 total。因为每个队员的得分必须相同,所以 score 必须是 total 的一个约数。
    • 排序:将分钟得分降序排序,以便在回溯时优先处理较大的数值,从而更快地剪枝。
    • 回溯检查 :对于每一个可能的 score(从最大值 maxtotal),检查是否可以将分钟得分分成 total / score 组,每组的和恰好是 score
  3. 回溯函数canPartitionKSubsets 函数尝试将分钟得分分配到 k 个组中,每个组的和不超过 LIMIT(即 score)。通过回溯的方式尝试所有可能的分配方案。

Java

java 复制代码
import java.util.*;
import java.util.stream.IntStream;
/**
 * @author code5bug
 */
public class Main {

    // 能否将数组等分成k组,每组和为LIMIT
    public static boolean canPartitionKSubsets(int[] arr, int k, int LIMIT) {
        int[] groups = new int[k];
        return backtrack(arr, 0, groups, LIMIT);
    }

    // 回溯函数:尝试将分钟得分分配到k个组中,每组和不超过LIMIT
    private static boolean backtrack(int[] nums, int idx, int[] groups, int LIMIT) {
        if (idx == nums.length) return true; // 所有分钟得分已分配完毕

        for (int i = 0; i < groups.length; i++) {
            if (groups[i] + nums[idx] > LIMIT) continue; // 当前组和超过LIMIT,跳过
            if (i > 0 && groups[i] == groups[i - 1]) continue; // 避免重复分配

            groups[i] += nums[idx]; // 尝试将当前分钟得分分配到第i组
            if (backtrack(nums, idx + 1, groups, LIMIT)) return true; // 递归检查剩余分钟得分
            groups[i] -= nums[idx]; // 回溯
        }

        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 有得分的分钟数
        int t = sc.nextInt();

        int[] arr = new int[t];
        for (int i = 0; i < t; i++) {
            arr[i] = sc.nextInt(); // 每分钟的得分
        }

        // 降序排序,优化回溯剪枝
        Arrays.sort(arr);
        reverse(arr);

        int total = IntStream.of(arr).sum(); // 计算总得分
        int max = arr[0]; // 最大分钟得分

        // 遍历可能的score,从max到total
        for (int score = max; score <= total; score++) {
            if (total % score != 0) continue; // score必须是total的约数
            if (canPartitionKSubsets(arr, total / score, score)) {
                System.out.println(score); // 找到最小score,输出并退出
                break;
            }
        }
    }

    // 辅助函数:数组降序排序
    private static void reverse(int[] arr) {
        int left = 0, right = arr.length - 1;
        while (left < right) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
    }
}

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

相关推荐
程序猿阿越5 分钟前
Kafka源码(三)发送消息-客户端
java·后端·源码阅读
似水流年流不尽思念8 分钟前
Spring MVC 中的 DTO 对象的字段被 transient 修饰,可以被序列化吗?
后端·面试
whitepure11 分钟前
万字详解Java中的运算
java
似水流年流不尽思念12 分钟前
为啥 HashMap 中的 table 也被 transient 修饰?其目的是什么?
后端·面试
AAA修煤气灶刘哥12 分钟前
搞定 Redis 不难:从安装到实战的保姆级教程
java·redis·后端
MrSYJ15 分钟前
全局和局部AuthenticationManager
java·后端·程序员
sp4218 分钟前
白话 LRU 缓存及链表的数据结构讲解(二)
算法
界面开发小八哥20 分钟前
「Java EE开发指南」如何使用MyEclipse中的Web Fragment项目?
java·ide·java-ee·eclipse·myeclipse
PineappleCoder1 小时前
为什么说发布 - 订阅是代码的 “万能胶水”?解耦逻辑全解析
前端·javascript·算法