【041】2530. 执行 K 次操作后的最大分数[优先队列]

给定一个整数数组nums和一个整数k,从数组中选择一个下标,增加当前分数并用该数值的三倍ceiling值替换它,目标是找到在k次操作后能获得的最大分数。解决方案涉及使用优先队列来始终处理最大值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。你的 起始分数 为 0 。
在一步 操作 中:
选出一个满足 0 <= i < nums.length 的下标 i ,
将你的 分数 增加 nums[i] ,并且
将 nums[i] 替换为 ceil(nums[i] / 3) 。
返回在 恰好 执行 k 次操作后,你可能获得的最大分数。
向上取整函数 ceil(val) 的结果是大于或等于 val 的最小整数。

https://leetcode.cn/problems/maximal-score-after-applying-k-operations/

/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

package com.huawei.prac;

import java.util.PriorityQueue;
import java.util.Queue;

public class Solution11th {

    public static void main(String[] args) {
        int[] nums = {10, 10, 10, 10, 10};
        System.out.println(maxKelements(nums,5));
        System.out.println(maxKelements(new int[]{1,10,3,3,3}, 3));
    }

    /**
     * 2530. 执行 K 次操作后的最大分数[优先队列]
     *
     * @param nums 整数数组
     * @param k 可操作次数
     * @return 最大得分数
     */
    public static long maxKelements(int[] nums, int k) {
        Queue<Integer> priorityQueue = new PriorityQueue<>((x, y) ->  y - x);
        for (int num : nums) {
            priorityQueue.offer(num);
        }
        int num;
        long count = 0;
        while (k-- > 0) {
            num = priorityQueue.poll();
            count += num;
            // 向上取整
            priorityQueue.add((int) Math.ceil(num / 3.0));
        }
        return count;
    }
}

7-14 夺宝大赛 7-14 夺宝大赛 分数 25 作者 陈越 单位 浙江大学 夺宝大赛的地图是一个由 n×m 个方格子组成的长方形,主办方在地图上标明了所有障碍、以及大本营宝藏的位置。参赛的队伍一开始被随机投放在地图的各个方格里,同时开始向大本营进发。所有参赛队从一个方格移动到另一个无障碍的相邻方格(“相邻”是指两个方格有一条公共边)所花的时间都是 1 个单位时间。但当有多支队伍同时进入大本营时,必将发生火拼,造成参与火拼的所有队伍无法继续比赛。大赛规定:最先到达大本营并能活着夺宝的队伍获得胜利。 假设所有队伍都将以最快速度冲向大本营,请你判断哪个队伍将获得最后的胜利。 输入格式: 输入首先在第一行给出两个正整数 m 和 n(2<m,n≤100),随后 m 行,每行给出 n 个数字,表示地图上对应方格的状态:1 表示方格可通过;0 表示该方格有障碍物,不可通行;2 表示该方格是大本营。题目保证只有 1 个大本营。 接下来是参赛队伍信息。首先在一行中给出正整数 k(0<k<m×n/2),随后 k 行,第 i(1≤i≤k)行给出编号为 i 的参赛队的初始落脚点的坐标,格式为 x y。这里规定地图左上角坐标为 1 1,右下角坐标为 n m,其中 n 为列数,m 为行数。注意参赛队只能在地图范围内移动,不得走出地图。题目保证没有参赛队一开始就落在有障碍的方格里。 输出格式: 在一行中输出获胜的队伍编号和其到达大本营所用的单位时间数量,数字间以 1 个空格分隔,行首尾不得有多余空格。若没有队伍能获胜,则在一行中输出 No winner. 输入样例 1: 5 7 1 1 1 1 1 0 1 1 1 1 1 1 0 0 1 1 0 2 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 7 1 5 7 1 1 1 5 5 3 1 3 5 1 4 输出样例 1: 7 6 样例 1 说明: 七支队伍到达大本营的时间顺为:7、不可能、5、3、3、5、6,其中队伍 4 和 5 火拼了,队伍 3 和 6 火拼了,队伍 7 比队伍 1 早到,所以获胜。 输入样例 2: 5 7 1 1 1 1 1 0 1 1 1 1 1 1 0 0 1 1 0 2 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 7 7 5 1 3 7 1 1 1 5 5 3 1 3 5 输出样例 2: No winner. 代码长度限制 16 KB Java (javac) 时间限制 800 ms 内存限制 256 MB 其他编译器 时间限制 400 ms 内存限制 64 MB 讲一下思路
04-03
<think>嗯,用户的问题是关于夺宝大赛算法的实现思路,需要计算各队伍最快到达大本营的时间,并判断是否有火拼导致没有胜者。我得先理解清楚问题需求,然后一步步拆解。 首先,用户提到的“夺宝大赛”应该是一个算法题,可能涉及图论中的最短路径问题。每个队伍需要从起点出发,以最快时间到达大本营,而如果有多个队伍同时到达,就会发生火拼,导致没有胜者。所以关键点有两个:计算各队伍的最短时间,以及检查是否有重复的最短时间。 接下来,我需要确定如何建模这个问题。可能每个队伍的路径可以看作图中的节点和边,边权代表时间。这时候可能需要用Dijkstra算法或者BFS,具体取决于图的类型。如果边权都是非负的,Dijkstra比较合适;如果是无权图,BFS可能更高效。 然后,处理火拼的情况。需要收集所有队伍到达的时间,然后检查是否存在多个队伍有相同的最小时间。如果有,就输出没有胜者,否则输出最快时间。 可能的步骤是: 1. 输入处理:读取队伍数量、路径信息。 2. 构建图结构:可能需要邻接表或邻接矩阵。 3. 对每个队伍,计算最短路径时间。 4. 收集所有最短时间,找到最小值。 5. 统计最小值出现的数,超过一则判定火拼。 需要注意的是,不同队伍可能有不同的起点,所以每个队伍需要独立计算最短路径。或者题目中所有队伍的起点是否相同?假设起点可能不同,所以每个队伍的路径需要单独处理。 另外,时间计算的方式是什么?比如,边权是否代表时间,或者移动速度是否影响?假设边权直接就是时间单位,这样直接累加即可。 对于图的存储,可能需要每个节点代表一个位置,边有权重。这时候使用Dijkstra算法对每个队伍的起点到终点进行计算。 举个例子,假设有3个队伍,各自的起点分别是A、B、C,终点都是大本营D。每个队伍需要计算从各自起点到D的最短时间。然后收集这三个时间,找到最小的那个,再看是否有多个队伍达到这个最小值。 接下来是代码实现的思路。输入部分可能需要读取队伍数n,然后读取每个队伍的路径信息。比如每个队伍可能有m个路径段,每个路径段是u到v的时间t。或者题目是否给出整个图的结构,每个队伍可能选择不同的路径?这里可能需要更明确的问题描述,但用户没有给出具体输入格式,可能需要假设。 可能的输入格式是:每个队伍给出自己的起点和路径,或者整个图的结构是统一的,队伍的起点可能不同。例如,每个队伍必须从自己的起点出发,沿着图中的边到达终点。这种情况下,图的结构是共享的,每个队伍的起点不同,但终点相同(大本营)。 假设图的结构是统一的,每个队伍的起点不同,终点相同。那么需要为每个队伍运行最短路径算法,从他们的起点到终点。 然后,关于时间复杂度的问题。如果有n个队伍,每个队伍运行Dijkstra算法的时间复杂度是O(M + N log N),其中N是节点数,M是边数。所以总时间复杂度是n*(M + N log N)。如果n很大,可能需要优化,比如预先计算所有节点到终点的最短路径,因为终点是固定的。这时候可以将图反向,从终点出发计算到所有其他节点的最短路径,这样每个队伍的起点到终点的时间就是预先计算好的,只需要O(M + N log N)一计算,而不是n。这可能是一个优化点,但用户的问题可能不需要优化到这种程度,具体取决于输入规模。 但用户的问题中可能需要每个队伍有不同的路径,比如队伍可能选择不同的路径,而不仅仅是起点不同。这时候可能需要每个队伍有自己的路径结构,这可能比较复杂。不过这种情况可能性较小,通常这种题目中的路径结构是固定的,队伍的位置不同。所以可能还是统一图的结构,不同起点。 回到问题,假设图是统一的,每个队伍有不同的起点,终点是同一个大本营。那么优化方法是反向图,计算终点到所有节点的最短路径,这样每个队伍的到达时间就是其起点的最短路径值。这样可以节省时间。 接下来,具体步骤: 1. 读取输入,构建图结构。可能包括节点数和边数,或者每个边由输入给出。 2. 构建反向图,将边的方向反转,因为我们要从终点出发计算到各个起点的最短路径。 3. 使用Dijkstra算法计算终点到所有其他节点的最短路径。 4. 对于每个队伍的起点,查找其对应的最短时间。 5. 收集所有队伍的时间,找到最小值,统计出现数。 6. 根据统计结果输出答案。 这样处理的话,时间复杂度会大大降低,特别是当队伍数量很大时。 然后,关于火拼的判断,只需要检查所有队伍的最短时间中的最小值是否有重复。例如,如果有三个队伍的时间是5、5、6,那么最小值是5,出现两,所以火拼,无胜者。如果最小值唯一,则输出该时间和对应的队伍。 代码实现的大致步骤: - 输入处理:可能需要读取节点数、边数,然后边信息。然后读取每个队伍的起点。 - 构建反向图。 - 运行Dijkstra得到终点到所有节点的最短距离。 - 收集各队伍的时间。 - 处理结果。 需要注意的是,如果某个队伍的起点无法到达终点,那么该队伍无法到达,可能需要排除这些情况,或者题目保证所有队伍都能到达。假设题目中所有队伍都能到达。 现在,假设用户的问题中的路径是每个队伍自己选择的,可能路径是直接给出的,比如每个队伍给出自己经过的路径点,这时候需要计算该路径的总时间,并找出所有队伍中最快的时间。这时候,问题就转化为计算每个队伍路径的总时间,然后比较。如果有路径不合法(比如中间无法连通),则该队伍的时间无效。但这种情况可能比较复杂。不过根据用户的问题描述,“计算各队伍最快到达大本营的时间”,可能意味着每个队伍可以选择自己的路径,因此需要计算他们各自的最短路径。 这种情况下,正确的处理方式是每个队伍独立计算从起点到终点的最短路径。这时候,如果图是统一的,那么反向图的方法更高效。 现在回到用户的问题,需要给出算法思路,所以需要分步骤说明: 1. 构建图模型:将各个地点作为节点,路径作为有向边,时间为边权。 2. 预处理最短路径:使用反向图,从大本营(终点)出发,计算到所有其他节点的最短时间。这样,每个队伍的起点到终点的时间即为预处理后的值。 3. 收集各队伍的时间:对于每个队伍的起点,查找预处理得到的最短时间。 4. 确定最快时间和火拼情况:找到所有时间中的最小值,统计出现数。若数大于1,则火拼,否则输出该时间。 这样处理的时间复杂度较低,适用于大规模数据。 接下来,考虑是否有特殊情况,比如多个队伍的时间相同但并非最小,比如存在两个队伍的时间为10,而最小时间是5,这时候他们不会导致火拼。火拼仅在所有队伍中最快时间有多个的情况下才会发生。 在代码中,需要遍历所有队伍的时间,找到其中的最小值,然后统计该最小值出现的数。如果数≥1且唯一,则输出胜者,否则输出无胜者。 可能的Python代码结构: 读取n(队伍数) 读取m(边数)和节点数等(如果有的话) 构建反向邻接表 使用Dijkstra计算终点到各点的最短时间 读取每个队伍的起点,存入列表 计算各队伍的时间,收集到times数组 min_time = min(times) count = times.count(min_time) if count ==1: print(min_time) else: print("无胜者") 但需要处理图的构建部分,比如边的输入方式。比如,每条边是u到v,时间t,那么在反向图中,存储为v到u,时间t。 例如,原图中的边u→v,时间t,在反向图中变为v→u,时间t。这样,当从终点出发运行Dijkstra时,得到的到起点s的最短时间,就是原图中s到终点的最短时间。 这样处理是否正确?是的,因为反向图中的路径v→u对应原图中的u→v,所以反向图中的路径相当于原图中的逆向路径。因此,从终点出发到各个节点的最短路径,对应原图中各个节点到终点的最短路径。 这样处理是正确的,可以节省大量时间,特别是当队伍数量多时。 综上,算法思路是: - 反向建图,使用Dijkstra算法预处理所有节点到大本营的最短时间。 - 收集各队伍的时间,判断最小时间是否唯一。 现在,用户的问题中还可能需要处理火拼的情况,即多个队伍同时到达的情况。这里的“同时”指的是到达时间相同,所以只要统计各队伍的最短时间中的最小值出现的数即可。 因此,算法步骤明确,接下来需要将这些步骤用中文清晰地解释,并给出可能的代码实现。 可能的代码部分需要注意,Dijkstra的实现需要优先队列,Python中可以用heapq模块。另外,处理无穷大的情况,比如用float('inf')表示无法到达,但题目可能假设所有队伍都能到达。 最后,测试样例可能有: 比如,三个队伍,他们的起点到终点的最短时间分别是5、5、6,那么输出无胜者。如果时间是3、5、6,则输出3。 综上,这是解决问题的思路。</think>### 夺宝大赛算法实现思路 #### 1. 问题建模与最短路径计算 将地图抽象为带权有向图,节点代表地点,边权代表移动时间。使用**反向图+Dijkstra算法**预处理所有节点到大本营的最短时间[^1]: 1. 构建反向图:将原始图中的边方向调转 2. 从大本营(终点)出发执行Dijkstra算法,计算到各节点的最短时间 3. 每个队伍的最快到达时间即为其起点在预处理结果中对应的值 $$ \text{最短时间} = \min_{p \in \text{路径集合}} \sum_{e \in p} t_e $$ #### 2. 火拼判断逻辑 收集所有队伍的到达时间后: 1. 找出最小到达时间$t_{min}$ 2. 统计$t_{min}$出现数 3. 若出现数>1则判定发生火拼 #### 3. 算法实现(Python示例) ```python import heapq def calculate_arrival_times(n, edges, destination): # 构建反向图 graph = defaultdict(list) for u, v, t in edges: graph[v].append((u, t)) # 反向存储边 # Dijkstra算法 dist = {i: float('inf') for i in graph} dist[destination] = 0 heap = [(0, destination)] while heap: time, node = heapq.heappop(heap) if time > dist[node]: continue for neighbor, t in graph[node]: if dist[neighbor] > time + t: dist[neighbor] = time + t heapq.heappush(heap, (dist[neighbor], neighbor)) return dist # 示例输入 teams = ['A', 'B', 'C'] # 各队伍起点 edges = [ ('A', 'B', 2), ('B', 'C', 3), ('C', 'Base', 5), ('B', 'Base', 7) ] destination = 'Base' # 计算各队时间 dist = calculate_arrival_times(len(teams), edges, destination) arrival_times = [dist[start] for start in teams] # 判断结果 min_time = min(arrival_times) count = arrival_times.count(min_time) if count == 1: print(f"获胜时间:{min_time}") else: print("无胜者(发生火拼)") ``` #### 4. 复杂度分析 - 时间复杂度:$O(E + V \log V)$(Dijkstra算法复杂度) - 空间复杂度:$O(V + E)$(存储图结构)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值