3117. 划分数组得到最小的值之和

3117. 划分数组得到最小的值之和


题目链接:3117. 划分数组得到最小的值之和

代码如下:

//参考链接:https://leetcode.cn/problems/minimum-sum-of-values-by-dividing-array/solutions/2739258/ji-yi-hua-sou-suo-jian-ji-xie-fa-by-endl-728z
class Solution 
{
public:
    int minimumValueSum(vector<int>& nums, vector<int>& andValues) 
    {
        const int INF = INT_MAX / 2; // 除 2 防止下面 + nums[i] 溢出
        int n = nums.size(), m = andValues.size();
        unordered_map<long long, int> memo;
        auto dfs = [&](auto&& dfs, int i, int j, int and_) -> int
        {
            if (n - i < m - j) // 剩余元素不足
            { 
                return INF;
            }
            if (j == m)// 分了 m 段
             { 
                return i == n ? 0 : INF;
            }
            and_ &= nums[i];
            // 三个参数压缩成一个 long long
            long long mask = (long long) i << 36 | (long long) j << 32 | and_;
            if (memo.contains(mask)) { // 之前计算过
                return memo[mask];
            }
            int res = dfs(dfs, i + 1, j, and_); // 不划分
            if (and_ == andValues[j]) // 划分,nums[i] 是这一段的最后一个数
            { 
                res = min(res, dfs(dfs, i + 1, j + 1, -1) + nums[i]);
            }
            return memo[mask] = res; // 记忆化
        };
        int res = dfs(dfs, 0, 0, -1);
        return res < INF ? res : -1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值