力扣每日一题638:大礼包

  题目描述:

在 LeetCode 商店中, 有 n 件在售的物品。每件物品都有对应的价格。然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品。

给你一个整数数组 price 表示物品价格,其中 price[i] 是第 i 件物品的价格。另有一个整数数组 needs 表示购物清单,其中 needs[i] 是需要购买第 i 件物品的数量。

还有一个数组 special 表示大礼包,special[i] 的长度为 n + 1 ,其中 special[i][j] 表示第 i 个大礼包中内含第 j 件物品的数量,且 special[i][n] (也就是数组中的最后一个整数)为第 i 个大礼包的价格。

返回 确切 满足购物清单所需花费的最低价格,你可以充分利用大礼包的优惠活动。你不能购买超出购物清单指定数量的物品,即使那样会降低整体价格。任意大礼包可无限次购买。

示例 1:

输入:price = [2,5], special = [[3,0,5],[1,2,10]], needs = [3,2]
输出:14
解释:有 A 和 B 两种物品,价格分别为 ¥2 和 ¥5 。 
大礼包 1 ,你可以以 ¥5 的价格购买 3A 和 0B 。 
大礼包 2 ,你可以以 ¥10 的价格购买 1A 和 2B 。 
需要购买 3 个 A 和 2 个 B , 所以付 ¥10 购买 1A 和 2B(大礼包 2),以及 ¥4 购买 2A 。

示例 2:

输入:price = [2,3,4], special = [[1,1,0,4],[2,2,1,9]], needs = [1,2,1]
输出:11
解释:A ,B ,C 的价格分别为 ¥2 ,¥3 ,¥4 。
可以用 ¥4 购买 1A 和 1B ,也可以用 ¥9 购买 2A ,2B 和 1C 。 
需要买 1A ,2B 和 1C ,所以付 ¥4 买 1A 和 1B(大礼包 1),以及 ¥3 购买 1B , ¥4 购买 1C 。 
不可以购买超出待购清单的物品,尽管购买大礼包 2 更加便宜。

解题思路

  1. 首先,过滤掉那些购买大礼包比单独购买更贵的大礼包。
  2. 使用深度优先搜索(DFS)和记忆化递归来解决问题。在每一步中,我们可以选择购买一个大礼包或者不购买。
  3. 对于每个大礼包,如果当前需求可以满足这个大礼包的要求,则尝试使用这个大礼包,并递归地计算剩余需求的最小价格。
  4. 比较不使用任何大礼包时的总价格和使用大礼包后的总价格,取较小值作为结果。
  5. 使用记忆化来避免重复计算相同的需求组合,提高效率。

代码实

class Solution {
public:
    int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs) {
        vector<vector<int>> usefulSpecials;
        // 过滤无用的大礼包
        for (auto& subSpe : special) {
            int spePrice = 0;
            for (int i = 0; i < subSpe.size() - 1; ++i) {
                spePrice += subSpe[i] * price[i];
            }
            if (spePrice > subSpe.back()) {
                usefulSpecials.push_back(subSpe);
            }
        }

        // 使用哈希表进行记忆化
        unordered_map<string, int> memo;
        return dfs(price, usefulSpecials, needs, memo);
    }

private:
    string needsToString(const vector<int>& needs) {
        string res;
        for (int need : needs) {
            res += to_string(need) + ",";
        }
        return res;
    }

    int dfs(vector<int>& price, vector<vector<int>>& specials, vector<int>& needs, unordered_map<string, int>& memo) {
        string key = needsToString(needs);
        if (memo.count(key)) return memo[key];

        int minPrice = 0;
        for (int i = 0; i < needs.size(); ++i) {
            minPrice += needs[i] * price[i];
        }

        for (auto& special : specials) {
            vector<int> newNeeds;
            bool valid = true;
            for (int i = 0; i < needs.size(); ++i) {
                if (needs[i] < special[i]) {
                    valid = false;
                    break;
                }
                newNeeds.push_back(needs[i] - special[i]);
            }
            if (valid) {
                minPrice = min(minPrice, special.back() + dfs(price, specials, newNeeds, memo));
            }
        }

        memo[key] = minPrice;
        return minPrice;
    }
};

【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)内容概要:本文介绍了基于蒙特卡洛拉格朗日方法的电动汽车充电站有序充电调度优化方案,重点在于采用分散式优化策略应对分时电价机制下的充电需求管理。通过构建数学模型,结合不确定性因素如用户充电行为电网负荷波动,利用蒙特卡洛模拟生成大量场景,并运用拉格朗日松弛法对复杂问题进行分解求解,从而实现全局最优或近似最优的充电调度计划。该方法有效降低了电网峰值负荷压力,提升了充电站运营效率经济效益,同时兼顾用户充电便利性。 适合人群:具备一定电力系统、优化算法Matlab编程基础的高校研究生、科研人员及从事智能电网、电动汽车相关领域的工程技术人员。 使用场景及目标:①应用于电动汽车充电站的日常运营管理,优化充电负荷分布;②服务于城市智能交通系统规划,提升电网交通系统的协同水平;③作为学术研究案例,用于验证分散式优化算法在复杂能源系统中的有效性。 阅读建议:建议读者结合Matlab代码实现部分,深入理解蒙特卡洛模拟拉格朗日松弛法的具体实施步骤,重点关注场景生成、约束处理迭代收敛过程,以便在实际项目中灵活应用改进。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值