【Leetcode】3180. 执行操作可获得的最大总奖励 I——1849

题目

3180. 执行操作可获得的最大总奖励 I

给你一个整数数组 rewardValues,长度为 n,代表奖励的值。

最初,你的总奖励 x 为 0,所有下标都是未标记的。你可以执行以下操作任意次

  • 从区间[0, n - 1]中选择一个未标记的下标i

  • 如果 rewardValues[i] 大于 你当前的总奖励 x,则将 rewardValues[i] 加到 x 上(即 x = x + rewardValues[i]),并 标记下标 i
    以整数形式返回执行最优操作能够获得的最大总奖励。

  • \(1\leq rewardValues.length\leq 2000\)

  • \(1\leq rewardValues[i]\leq 2000\)

思路

首先可以想到的就是最大的数字一定是需要选定的
证明方法是反证法。假定最后选择的数字不是最大的数字x,那么最大的数字一定是不小于这个x的,因此不选择其他的更多数字,仅仅将x替换为最大的数字也是不差于原始的结果的,因此最后选择的数字一定是最大的数字。

因此,考虑到上述分析最后一次一定是选择最大的数字,那么为了满足题目的条件,那么就需要找到一个组合即他们的和不超过最大的数字。

而考虑到数据的范围,数字的范围不算大,因此考虑将能否选择到该数字作为动态规划的对象。

class Solution:
    def maxTotalReward(self, rewardValues: List[int]) -> int:
        rewardValues.sort()
        dp = [False]*(rewardValues[-1])
        dp[0] = True
        n = len(rewardValues)
        for i in range(n-1):
            for j in range(rewardValues[i]):
                if rewardValues[i] + j>=rewardValues[-1]: break
                dp[rewardValues[i]+j] |= dp[j]
        for i in range(rewardValues[-1]-1,-1,-1):
            if dp[i]: return i+rewardValues[-1]
        return -1

算法时间复杂度为\(O(N^2)\)

接下来展示的是python魅力时刻。

class Solution:
    def maxTotalReward(self, nums: List[int]) -> int:
        f = 1
        for x in sorted(set(nums)):
            f |= (f & ((1 << x) - 1))<<x
        return f.bit_length()-1
posted @ 2024-10-25 17:07  TICSMC  阅读(29)  评论(0)    收藏  举报