Leetcode 638. 大礼包【DFS & DFS+回溯】

问题描述

在LeetCode商店中, 有许多在售的物品。

然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品。

现给定每个物品的价格,每个大礼包包含物品的清单,以及待购物品清单。请输出确切完成待购清单的最低花费。

每个大礼包的由一个数组中的一组数据描述,最后一个数字代表大礼包的价格,其他数字分别表示内含的其他种类物品的数量。

任意大礼包可无限次购买。

示例 1:

输入: [2,5], [[3,0,5],[1,2,10]], [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。
说明:

  • 最多6种物品, 100种大礼包。
  • 每种物品,你最多只需要购买6个。
  • 你不可以购买超出待购清单的物品,即使更便宜。

解题报告

略。

实现代码

  • DFS 另外申请变量 clone 来记录信息
class Solution {
public:
    int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs) {
        // unordered_map<vector<int>, int>mp;
        return shopping(price, special, needs);
        // return 0;
    }
    int shopping(vector<int>& price, vector<vector<int>>& special, vector<int>& needs){
        // if(mp.find(needs)!=mp.end()) return mp[needs];
        int i=0, ans = dot(needs, price);
        for(auto item:special){
            vector<int>clone(needs.begin(), needs.end());
            for(i=0;i<needs.size();i++){
                int diff = clone[i]-item[i];
                if(diff<0)  break;
                else clone[i]=diff;
            }
            if(i==needs.size()) ans= min(ans, item[i]+shopping(price, special, clone));
        } 
        // mp[needs]=ans;
        return ans;
    }
    int dot(vector<int>a, vector<int>b) {
        int sum = 0;
        for (int i = 0; i < a.size(); i++) sum += a[i] * b[i];
        return sum;
    }
};
  • 回溯
class Solution {
public:
    int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs) {
        //do not use coupon
        int res = 0, n = price.size();
        for(int i = 0; i < n;i++) {
            res += price[i] * needs[i];
        }
        
        for(auto offer: special) {
            bool isValid = true;
            for(int j = 0; j < n;j++) {
                //you cannot use this coupon
                if(needs[j] < offer[j]) {
                    isValid = false;
                }
                needs[j] -= offer[j];
            }
            if(isValid) {
                res = min(res, shoppingOffers(price,special,needs) + offer.back());
            }
            for(int j =0 ; j < n; j++) {
                needs[j] += offer[j];
            }
        }
        return res;
        
    }
};

参考资料

[1] Leetcode 638. 大礼包
[2] 官方题解
[3] 评论区:Tori

猜你喜欢

转载自blog.csdn.net/qq_27690765/article/details/106544340
今日推荐