• Java实现 LeetCode 638 大礼包(阅读理解题,DFS)


    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个。
    你不可以购买超出待购清单的物品,即使更便宜。
    

    PS:
    经典DFS,除了操作复杂以外,
    简述题目:
    三个list,第一个list是每个物品单价,
    第二个list是大礼包详情,每个大礼包中最后一个为大礼包的价格,前面的是礼包中各个物品的数量,
    第三个list是你需要购买的各个物品的数量

    class Solution {
        //全局保存
       private List<Integer> global_needs, global_price;
        private List<List<Integer>> global_special;
        private int sum = 0, res = Integer.MAX_VALUE;
    
        public int shoppingOffers(List<Integer> price, List<List<Integer>> special, List<Integer> needs) { 
            global_needs = needs;
            global_special = special;
            global_price = price;
            find(0);
            return res;
        }
    
        private void find(int begin) { 
            int temp_sum = sum;
            // 最坏的情况单价买
            for (int i = 0; i < global_needs.size(); ++i)
                sum += global_needs.get(i) * global_price.get(i); 
            res = Math.min(res, sum);
            
            sum = temp_sum; 
            for (int i = begin; i < global_special.size(); ++i) { 
                List<Integer> cur_special = global_special.get(i); 
                int special_num = cal_special_num(cur_special);  
                    for (int j = 1; j <= special_num; ++j) { 
    
                        List<Integer> temp_needs = new ArrayList<>(global_needs); 
    
                        for (int k = 0; k < global_needs.size(); ++k)
                            global_needs.set(k, global_needs.get(k) - cur_special.get(k) * j); 
                        sum += cur_special.get(global_needs.size()) * j;
                        
                        find(i + 1); 
    
                        global_needs = temp_needs; 
                        sum = temp_sum;
                    }
                
            }
        }
    
        //最多需要多少
        private int cal_special_num(List<Integer> item) { 
            int max = Integer.MAX_VALUE;
            for (int i = 0; i < global_needs.size(); ++i) { 
                if (global_needs.get(i) < item.get(i))
                    return 0; 
                if (item.get(i) != 0)
                    max = Math.min(global_needs.get(i) / item.get(i), max);
            }
            return max;
        }
    }
    
  • 相关阅读:
    使用 Fiddler 对android模器进行Http监控(转)
    UDID替代方案(转)
    iPhone用nib/xib文件载入窗口,和用代码写窗口,到底哪个快?(转)
    UINavigationController修改默认的动画
    《Programming WPF》翻译 第8章 5.创建动画过程
    《Programming WPF》翻译 第8章 6.我们进行到哪里了?
    《Programming WPF》翻译 第8章 2.Timeline
    《Programming WPF》翻译 第9章 4.模板
    《Programming WPF》翻译 第9章 1.自定义控件基础
    《Programming WPF》翻译 第9章 前言
  • 原文地址:https://www.cnblogs.com/a1439775520/p/13074860.html
Copyright © 2020-2023  润新知