小C大作战得分计算 | 豆包MarsCode AI刷题

55 阅读3分钟

问题描述

在游戏“小C大作战”中,每个角色都有一个能量值ai,能量大的角色可以击败能量小的角色,并获得对应的分数。每个角色被击败后,击败者可以获得bi得分。为了维持游戏平衡,每个角色最多只能击败mm个其他角色。请计算出每个角色最终可以获得的最大分数。 保证这些球的能量值两两不同。

思路:  根据题目的意思我们只要对ai排一下序,相应的bi也和ai一样排序。那么对ai说,索引比他小的那些bi就是可以获取的分数,然后我们选取这些最大的前m个的和就是每个角色可以获得的最大分数。

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public class 小C大作战得分计算 {


    public static int[] solution(int n, int m, int[] a, int[] b) {
        // write code here
        Map<Integer,Integer> map=new TreeMap<>();
        //因为题目向我们保证ai是不同的,所以不用担心覆盖的问题,直接hashmap记录ai的索引,key是ai,value是索引
        Map<Integer,Integer> a_index=new HashMap<>();
        for (int i = 0; i < n; i++) {
            map.put(a[i],b[i]);
            a_index.put(a[i],i);
        }
        int[] res=new int[n];
        AtomicInteger l= new AtomicInteger();
        AtomicInteger sum= new AtomicInteger();

        //FIXME:这里还是不能用队列,因为要选出ai小于这个值前面最大的m个!,要用优先队列
        Queue<Integer> que=new PriorityQueue<>();

        //这是TreeMap已经按大小顺序排好了!
        map.forEach((k,v)->{
            if(l.get()<n) {
                //第k个的得分是比这个ai小的数的m个最大bi的和
                res[a_index.get(k)] = sum.get();
                if (que.size() == m) {
                    que.add(v);
                    int diu=-que.poll();
                    //System.out.println(diu);
                    sum.addAndGet(diu);
                    sum.addAndGet(v);
                } else {
                    sum.addAndGet(v);
                    que.add(v);
                }
            }
            l.getAndIncrement();
        });
        System.out.println(Arrays.toString(res));
        return res; // Placeholder
    }

    public static void main(String[] args) {
        System.out.println(Arrays.equals(solution(5, 3, new int[]{1, 3, 5, 2, 4}, new int[]{1, 2, 3, 4, 5}), new int[]{0, 5, 11, 1, 7}));
        System.out.println(Arrays.equals(solution(4, 2, new int[]{10, 20, 30, 40}, new int[]{2, 4, 6, 8}), new int[]{0, 2, 6, 10}));
        System.out.println(Arrays.equals(solution(6, 1, new int[]{6, 12, 18, 24, 30, 36}, new int[]{5, 10, 15, 20, 25, 30}), new int[]{0, 5, 10, 15, 20, 25}));
            System.out.println(Arrays.equals(solution(6, 3, new int[]{14,13,15,6,9,3}, new int[]{4,6,7,1,16,6}), new int[]{0, 2, 6, 10}));
    }
}

一、解题思路

  1. 对能量值数组a进行排序,同时将得分数组b按照a的排序顺序进行调整。
  2. 使用哈希表记录每个能量值对应的索引,方便后续计算。
  3. 遍历排序后的能量值数组,对于每个角色,计算其可以击败的其他角色数量,并从这些角色的得分中选择最大的m个进行累加。
  4. 使用优先队列(最小堆)来维护当前可击败角色中的最大得分。

二、代码实现

  1. 使用TreeMap和HashMap分别记录得分和能量值的对应关系以及能量值对应的索引。
  2. 初始化结果数组res,用于存储每个角色最终可以获得的最大分数。
  3. 遍历TreeMap,对于每个角色,计算其可以击败的其他角色数量,并从这些角色的得分中选择最大的m个进行累加。
  4. 使用优先队列维护当前可击败角色中的最大得分。当队列大小超过m时,移除最小值,并更新累加得分。