638.大礼包

在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。
示例 2:

输入: [2,3,4], [[1,1,0,4],[2,2,1,9]], [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更加便宜。

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

来源:力扣(LeetCode)


这题咋说呢,虽然写了一个小时左右,但还真是中等里面独立思考和完成的一道题。
赶紧写一下此题的思路形成:
1.这个题要递归。递归要怎么解决呢?
2.奥,需要递归列出所有的可能解,找出最小的答案就可以了。
3.递归的几个要素要怎么写呢?

  • 结束条件:不能多买,要正好才行。后来又发展到,没有剩余即可(要买的都买完了)。
    中间有个过程,是思考了一下这个递归要解决的问题把东西买完了就行。想到这里恍然大悟,所以结束条件必然是东西买完了就可以了。开始想的是递归的结束条件,而没有想到用这个递归来解决的实际问题。脱离了实际。下次不妨想想,这个事情我做到啥程度才不做了
  • 主体:主题必然是买东西了
    • 首先先买大礼包,之后再买单品。
    • 买大礼包要看看能不能买。能买,递归;不能买,看下一个大礼包。
    • 最后查漏补缺,把没买的买单品。
    • 写完犹豫了一下,应该是大礼包和单品的优先级 (当时理解成代码的执行顺序 )是一样的,应该放在一起。后来又一想,大礼包肯定优惠啊。

4 . 最后发现答案不对,想了想原来是中间一个变量错了( ans-=special[i][j]; 没有这一行)。改了,成功。
最后关于那个优先级问题,加上 ans-=special[i][j],后来一想,这样优先级就一样了。现在的理解是,就是都有机会买到而已。
或者改为dfs(price,special,needs,ans+special[i][j])即可。

int eans=0x3f3f3f3f;
    int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs) {
      
        dfs(price,special,needs,0);
        return eans;
    }
    void dfs(vector<int>& price, vector<vector<int>>& special, vector<int>& needs,int ans){
        int flag=0;
        for(auto a:needs){
            flag+=a;
        }
        if(flag==0){
            eans=min(ans,eans);
            return;
        } 
        //需要的  都  买完了。所以结束递归,返回价钱。

        //开始买大礼包
        for(int i=0;i<special.size();i++){
            //看看大礼包能不能买,不能买的的话,看下一个大礼包
            int flag1=true;
            int j;
            for(j=0;j<needs.size();j++){
                if(special[i][j]>needs[j]) {
                    flag1=false;
                    break;
                }
            }

            //要是可以买大礼包,则递归
            if(flag1){
                ans+=special[i][j];//把大礼包的价钱加上
                for(j=0;j<special[i].size()-1;j++) needs[j]-=special[i][j];//把需求减去
                dfs(price,special,needs,ans);//继续看下一个礼包,
                //递归之后,需要需求加回来
                for(j=0;j<special[i].size()-1;j++) needs[j]+=special[i][j];
                ans-=special[i][j];//把大礼包的价钱减去
            }
        }
        //大礼包买完了,开始买单价商品
        vector<int>tep=needs;
        int tepp=0;
        for(int i=0;i<needs.size();i++){
            if(needs[i]!=0){
                tepp+=needs[i]*price[i];
                needs[i]=0;
            }
        }
        ans+=tepp;
        //cout<<ans<<endl;
        dfs(price,special,needs,ans);
        needs=tep;
        ans-=tepp;
    }
发布了161 篇原创文章 · 获赞 68 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43179428/article/details/104310922