鱼C论坛

 找回密码
 立即注册
查看: 1845|回复: 2

[技术交流] C++刷LeetCode(638. 大礼包)【回溯】

[复制链接]
发表于 2020-6-20 22:50:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
题目描述:
  1. 在LeetCode商店中, 有许多在售的物品。

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

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

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

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

  6. 示例 1:

  7. 输入: [2,5], [[3,0,5],[1,2,10]], [3,2]
  8. 输出: 14
  9. 解释:
  10. 有A和B两种物品,价格分别为¥2和¥5。
  11. 大礼包1,你可以以¥5的价格购买3A和0B。
  12. 大礼包2, 你可以以¥10的价格购买1A和2B。
  13. 你需要购买3个A和2个B, 所以你付了¥10购买了1A和2B(大礼包2),以及¥4购买2A。
  14. 示例 2:

  15. 输入: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1]
  16. 输出: 11
  17. 解释:
  18. A,B,C的价格分别为¥2,¥3,¥4.
  19. 你可以用¥4购买1A和1B,也可以用¥9购买2A,2B和1C。
  20. 你需要买1A,2B和1C,所以你付了¥4买了1A和1B(大礼包1),以及¥3购买1B, ¥4购买1C。
  21. 你不可以购买超出待购清单的物品,尽管购买大礼包2更加便宜。
  22. 说明:

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

  26. 来源:力扣(LeetCode)
  27. 链接:https://leetcode-cn.com/problems/shopping-offers
  28. 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
复制代码


  1. class Solution {
  2. public:
  3.     bool valid(vector<int>&store, vector<int>&needs){
  4.         for(int i = 0 ; i < store.size() - 1; i++){
  5.             if(store[i] > needs[i]) return false;
  6.         }
  7.         return true;
  8.     }
  9.     void dfs(vector<int>&price, vector<vector<int> >&store, vector<int>&needs, int & res, int sum){
  10.         if(sum > res) return;
  11.         int number = accumulate(needs.begin(), needs.end(), 0);
  12.         if(number == 0){//你不可以购买超出待购清单的物品,即使更便宜。
  13.             res = min(res, sum);
  14.             return;
  15.         }
  16.         bool match = false;
  17.         for(int i = 0; i < store.size(); i++){
  18.             if(valid(store[i], needs)){
  19.                 match = true;
  20.                 for(int j = 0; j < store[0].size() - 1; j++){
  21.                     needs[j] -= store[i][j];
  22.                 }
  23.                 dfs(price, store, needs, res, sum + store[i].back());
  24.                 for(int j = 0; j < store[0].size() - 1; j++){
  25.                     needs[j] += store[i][j];
  26.                 }
  27.             }
  28.         }
  29.         if(match == false){
  30.             for(int i = 0; i < needs.size(); i++){
  31.                 sum += needs[i] * price[i];
  32.             }
  33.             res = min(res, sum);
  34.         }
  35.     }
  36.     int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs) {
  37.         //采用贪心的算法,先在不超过needs数的情况下尽可能的先选组合,最后再单买
  38.         //去除组合大于单买和大于需要个数的组合数
  39.         int len1 = special.size(), len2 = special[0].size();
  40.         vector<vector<int> > store;
  41.         for(int i = 0; i < len1; i++){
  42.             int temp = 0;
  43.             bool flag = true;
  44.             for(int j = 0 ; j < len2 - 1; j++){
  45.                 temp += special[i][j] * price[j];
  46.                 if(special[i][j] > needs[j]) flag = false;
  47.             }
  48.             if(flag && temp > special[i][len2-1]) store.push_back(special[i]);
  49.         }
  50.         int res = INT_MAX;
  51.         dfs(price, store, needs, res, 0);
  52.         return res;

  53.     }
  54. };
复制代码


注意事项:
  1. 下面这样的输入没有办法实现,正常应该是5,而得到的结果是16。这道题应该是把这种情况剔除掉了。

  2. price = [2,5]
  3. special = [[4,2,5]]
  4. needs = [3,2]
复制代码



代码参考链接:https://leetcode-cn.com/problems ... fa-by-da-li-wang-6/

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-6-20 22:51:41 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-6-21 08:50:33 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-8-6 02:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表