每日一题:收集巧克力

计算数组中巧克力的成本,通过周期性修改类型并考虑操作成本,找出收集所有类型巧克力的最小总成本。涉及动态规划和数组操作技巧。

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

给你一个长度为 n、下标从 0 开始的整数数组 numsnums[i] 表示收集位于下标 i 处的巧克力成本。每个巧克力都对应一个不同的类型,最初,位于下标 i 的巧克力就对应第 i 个类型。

在一步操作中,你可以用成本 x 执行下述行为:

  • 同时修改所有巧克力的类型,将巧克力的类型 i 修改为类型 ((i + 1) mod n)

假设你可以执行任意次操作,请返回收集所有类型巧克力所需的最小成本。

示例 1:

输入:nums = [20,1,15], x = 5
输出:13
解释:最开始,巧克力的类型分别是 [0,1,2] 。我们可以用成本 1 购买第 1 个类型的巧克力。
接着,我们用成本 5 执行一次操作,巧克力的类型变更为 [1,2,0] 。我们可以用成本 1 购买第 2 个类型的巧克力。
然后,我们用成本 5 执行一次操作,巧克力的类型变更为 [2,0,1] 。我们可以用成本 1 购买第 0 个类型的巧克力。
因此,收集所有类型的巧克力需要的总成本是 (1 + 5 + 1 + 5 + 1) = 13 。可以证明这是一种最优方案。

示例 2:

输入:nums = [1,2,3], x = 4
输出:6
解释:我们将会按最初的成本收集全部三个类型的巧克力,而不需执行任何操作。因此,收集所有类型的巧克力需要的总成本是 1 + 2 + 3 = 6 。

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 10^9
  • 1 <= x <= 10^9

抛开巧克力重新描述下这个题目:给定数组nums,每个下标对应着消除当前下标消耗的代价。同时可以对数组进行操作:每个数向前移动一位(头移动到尾),这个操作消耗的代价是x。请给出数组nums消除所有元素的最小代价。

对于提供的操作,最多进行n-1次,每次操作时可以判断移动前后代价的大小,保留更小的代价。

costs[j] = min(costs[j],nums[(i + j)%n]);

其中( i + j ) % n起到循环数组的作用。

上面只是比较了移动到当前次数 i 时,对应的消除操作代价,而没有包括移动操作代价。因而在外层循环中需要比较当前最小代价和进行这次移动后的代价。也就是移动后是否减小了整体代价。

 result = min(result,static_cast<long long>(i) * x + accumulate(costs.begin(), costs.end(), 0LL));

这里要注意需要对遍历的下标 i 转成long类型,否则会超出范围。

这个逻辑的基础是,消除的时机可以出现在任何时刻,而非移动后进行整体消除。

代码:

class Solution {
public:
    long long minCost(vector<int>& nums, int x) {
        int n = nums.size();
        vector<int> costs(nums);
        long long result = accumulate(costs.begin(), costs.end(), 0LL);
        for(int i = 1;i < n;i++){
            for(int j = 0;j < n;j++){
                costs[j] = min(costs[j],nums[(i + j)%n]);
            }
            result = min(result,static_cast<long long>(i) * x + accumulate(costs.begin(), costs.end(), 0LL));
        }
        return result;
    }
    
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值