华为OD机试真题——人气最高的店铺(2025B卷:200分)Java/python/JavaScript/C/C++/GO最佳实现

2025 B卷 200分 题型

本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享》

华为OD机试真题《人气最高的店铺》:


文章快捷目录

题目描述及说明

Java

python

JavaScript

C++

C

GO


题目名称:人气最高的店铺


  • 知识点:贪心算法、排序、逻辑分析
  • 时间限制:1秒
  • 空间限制:256MB
  • 限定语言:不限

题目描述

某购物城有m个商铺,现决定举办一场活动选出人气最高店铺。活动共有n位市民参与,每位市民只能投一票,但1号店铺如果给该市民发放q元的购物补贴,该市民会改为投1号店铺。请计算1号店铺需要最少发放多少元购物补贴才能成为人气最高店铺(即获得的票数要大于其他店铺)。如果1号店铺本身就是票数最高店铺,返回0。

输入描述

  • 第一行为小写逗号分割的两个整数n,m,分别表示参与的市民总数和店铺总数(1 ≤ n, m ≤ 3000)。
  • 第2到n+1行,每行为小写逗号分割的两个整数p,q,表示市民的意向投票情况:
    • p:该市民意向投票给p号店铺(1 ≤ p ≤ m)。
    • q:改投1号店铺所需给予的q元购物补贴(1 ≤ q ≤ 10^9)。

输出描述
1号店铺需要发放的最少购物补贴金额。

示例1
输入:

5,5  
2,10  
3,20  
4,30  
5,40  
5,90  

输出:

50  

说明:
最优策略是发放10元(抢2号店铺票)和40元(抢5号店铺票),总金额50元,使1号店铺获得2票,其他店铺最高票数为1票。

示例2
输入:

5,5  
2,10  
3,20  
4,30  
5,80  
5,90  

输出:

60  

说明:
最优策略是发放10元、20元、30元(抢2、3、4号店铺票),总金额60元,使1号店铺获得3票,其他店铺最高票数为2票。


Java

问题分析

我们需要确保1号店铺通过发放购物补贴成为人气最高的店铺。每位市民原本投票给其他店铺,但可以通过补贴使其改投1号。目标是找到最小的补贴金额,使得1号店铺的票数严格大于其他店铺的最高票数。

解题思路

  1. 统计初始票数:统计1号店铺的初始票数和其他店铺的票数。
  2. 贪心策略:通过枚举其他店铺允许的最高票数 t,计算1号店铺需要的最少票数 k = t + 1
  3. 动态规划:对于每个 t,计算必须抢的票数总和和可选抢的票数总和,取最小值。

代码实现

import java.util.*;
import java.util.stream.Collectors;

public class Main {
   
    public static void main(String[] args) {
   
        Scanner scanner = new Scanner(System.in);
        String[] nm = scanner.nextLine().split(",");
        int n = Integer.parseInt(nm[0]); 
        int m = Integer.parseInt(nm[1]); 

        List<Integer> shop1Voters = new ArrayList<>();
        Map<Integer, List<Integer>> otherShops = new HashMap<>();

        for (int i = 0; i < n; i++) {
   
            String[] pq = scanner.nextLine().split(",");
            int p = Integer.parseInt(pq[0]);
            int q = Integer.parseInt(pq[1]);
            if (p == 1) {
   
                shop1Voters.add(q);
            } else {
   
                otherShops.computeIfAbsent(p, k -> new ArrayList<>()).add(q);
            }
        }

        int c0 = shop1Voters.size(); // 1号店铺初始票数
        if (isInitialWinner(c0, otherShops)) {
   
            System.out.println(0);
            return;
        }

        // 预处理其他店铺的数据
        Map<Integer, List<Integer>> sortedQ = new HashMap<>();
        Map<Integer, long[]> prefixSums = new HashMap<>();
        Map<Integer, Integer> votes = new HashMap<>();
        for (Map.Entry<Integer, List<Integer>> entry : otherShops.entrySet()) {
   
            int p = entry.getKey();
            List<Integer> qList = entry.getValue();
            Collections.sort(qList);
            sortedQ.put(p, qList);
            votes.put(p, qList.size());
            long[] prefix = new long[qList.size() + 1];
            for (int i = 0; i < qList.size(); i++) {
   
                prefix[i + 1] = prefix[i] + qList.get(i);
            }
            prefixSums.put(p, prefix);
        }

        int maxInitialVote = votes.values().stream().max(Integer::compare).orElse(0);
        long minCost = Long.MAX_VALUE;

        // 枚举允许的其他店铺最高票数t
        for (int t = 0; t <= maxInitialVote; t++) {
   
            int k = t + 1;
            int requiredSteal = k - c0;
            if (requiredSteal < 0) continue;

            long sumS = 0; // 必须抢的票数总和
            long mandatoryCost = 0;
            boolean isValid = true;

            for (Map.Entry<Integer, List<Integer>> entry : sortedQ.entrySet()) {
   
                int p = entry.getKey();
                int vp = votes.get(p);
                int sp = Math.max(vp - t, 0);
                sumS += sp;

                long[] prefix = prefixSums.get(p);
                if (sp > prefix.length - 1) {
    // 无法满足必须抢的数目
                    isValid = false;
                    break;
                }
                mandatoryCost += prefix[sp];
            }

            if (!isValid || sumS > requiredSteal) continue;
            int additional = requiredSteal - (int) sumS;
            if (additional < 0) continue;

            List<Integer> candidates = new ArrayList<>();
            for (Map.Entry<Integer, List<Integer>> entry : sortedQ.entrySet()) {
   
                int p = entry.getKey();
                List<Integer> qList = entry.getValue();
                int vp = votes.get(p);
                int sp 

你可能感兴趣的:(华为OD,华为od,java,python,javascript,c语言,c++,GO)