深度优先搜索系列六- LeetCode 638 大礼包

题目

https://leetcode-cn.com/problems/shopping-offers/

大礼包.png

代码

class Solution {
public:
    int min;
    int shoppingOffers(vector& price, vector>& special, vector& needs) {
        min=calsingle(price,needs,0);
        search(price,special,needs,0);
        return min;
    }
    void search(vector& price, vector>& special, vector& needs,int current){
        for(int i=0;i>& special, vector& needs){
        for(int m=0;mneeds[m]) return false;
        }
        return true;
    }
    /* 选择i号礼包,从needs列表中减掉i 中每个产品数量*/
    void select(int i,vector>& special, vector& needs){
        for(int m=0;m>& special, vector& needs){
        for(int m=0;m& price,vector& needs,int current){
        int sum=0;
        for(int m=0;m

简析

这个题挺有意思的,从搜索回溯的角度想,按如下步骤思考

  • A for循环范围
  • B 判断是否可选
  • C 选择后的相关变量变化
  • D 回溯
  • E 最优解与结束条件等

通过此题能学到什么

  • 对于复杂题目,一定要封装一些小函数,这样主代码逻辑清晰,也易于修改与测试。
  • special[i].back(); 此处back()是向量中自带的函数,得到向量的最后一个数。

A for循环范围

礼包不止能买一个,所以所有礼包都可以选,for循环范围即为礼包向量的长度。

 for(int i=0;i

B 判断

判断即判断选上这个礼包后,是否超出购买个数。比如这个礼包有2个A,你还需要一个,这个就不能选。

/* 判断这个大礼包数量是否超过所需 */
    bool pd(int i ,vector>& special, vector& needs){
        for(int m=0;mneeds[m]) return false;
        }
        return true;
    }

C 选择后

选上后,将需求清单相应物品数量减少,总价加上礼包数

select(i,special,needs);//选上
current+=special[i].back();//当前总价把这个礼包价格加上
    /* 选择i号礼包,从needs列表中减掉i 中每个产品数量*/
    void select(int i,vector>& special, vector& needs){
        for(int m=0;m

D 回溯,和选择正相反

 /* 回溯i号礼包,从needs列表中加上i中每个产品数量*/
    void unselect(int i,vector>& special, vector& needs){
        for(int m=0;m

其他

目前为止,还缺点东西,怎么结束和得出最终结果。我们每选一个礼包后,剩下的需求清单中的物品都用单独购买凑一下,如果凑齐后的总价小于当前保存的最低价,最低价等于这个数。

int total=calsingle(price,needs,current);//计算补上单品后的总价
if(total
 /* 计算剩余needs列表全按单品购买的价格 */
    int calsingle(vector& price,vector& needs,int current){
        int sum=0;
        for(int m=0;m

你可能感兴趣的:(深度优先搜索系列六- LeetCode 638 大礼包)