638. Shopping Offers [LeetCode]

来源:互联网 发布:无法连接steam网络 编辑:程序博客网 时间:2024/06/07 02:31

In LeetCode Store, there are some kinds of items to sell. Each item has a price.

However, there are some special offers, and a special offer consists of one or more different kinds of items with a sale price.

You are given the each item's price, a set of special offers, and the number we need to buy for each item. The job is to output the lowest price you have to pay for exactly certain items as given, where you could make optimal use of the special offers.

Each special offer is represented in the form of an array, the last number represents the price you need to pay for this special offer, other numbers represents how many specific items you could get if you buy this offer.

You could use any of special offers as many times as you want.

Example 1:

Input: [2,5], [[3,0,5],[1,2,10]], [3,2]Output: 14Explanation: There are two kinds of items, A and B. Their prices are $2 and $5 respectively. In special offer 1, you can pay $5 for 3A and 0BIn special offer 2, you can pay $10 for 1A and 2B. You need to buy 3A and 2B, so you may pay $10 for 1A and 2B (special offer #2), and $4 for 2A.

Example 2:

Input: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1]Output: 11Explanation: The price of A is $2, and $3 for B, $4 for C. You may pay $4 for 1A and 1B, and $9 for 2A ,2B and 1C. You need to buy 1A ,2B and 1C, so you may pay $4 for 1A and 1B (special offer #1), and $3 for 1B, $4 for 1C. You cannot add more items, though only $9 for 2A ,2B and 1C.

Note:

  1. There are at most 6 kinds of items, 100 special offers.
  2. For each item, you need to buy at most 6 of them.
  3. You are not allowed to buy more items than you want, even if that would lower the overall price.


题目大意:这题的英文描述有点长,但实际上,看一下 example 和 note 就能明白题目要求我们干啥了。
给定三个 List ,分别表示各种商品的价格、特价组合和每种商品采购的需求。price 和 needs 的长度 n 表示商品的种类数。price[i] ,needs[i] 分别表示第 i 种商品的价格、需求量。special 列表中的每个元素,包含了组合中每种商品的数量和组合的购买价格。
每种组合的购买次数不限,但采购的商品不能有多余。要求出总价最低的采购方案的总金额。


思路概述:基本的思路就是采用DFS的递归算法,尝试用总需求减去 special 的供应量,如果新的需求不为负,深度优先递归,之后再加回减去的量。最后,需要对剩余需求量(没有匹配到合适的special)计算按单件采购的总金额,取较小的数返回



算法描述
<1>  result = max_value;
<2>  for i = 1 to special.size():
            offer = special[i];
            valid = true;  // 当前的 special 默认是有效的
            for j = 1 to needs.size():
                remain = needs[j] - offer[j];
                needs[j] = remain;
                if (valid && remain<0)    valid = false;  // special 供货量超过了需求量,不能采用该 special
            if (valid)    result = min(result,  go to<1> + offer.getPrice());  // 取最小的result
            for j = 1 to needs.size():
                needs[j] += offer[j];
<3>  for i = 1 to needs.size():
            nonOfferPrice += price[i] * needs[i];
<4>  return min(result, nonOfferPrice);


AC的代码如下
public class Solution {    public int shoppingOffers(List<Integer> price, List<List<Integer>> special, List<Integer> needs) {                int result = Integer.MAX_VALUE;                // dfs, try apply each offer to the needs, and then add back        for (int i=0; i<special.size(); i++) {            // get the target offer            List<Integer> offer = special.get(i);            // set offer application default valid            boolean valid = true;               // try to apply offer            for (int j=0; j<needs.size(); j++) {                // the remain need count after apply the offer                int remain = needs.get(j) - offer.get(j);                   // set needs with new value                needs.set(j, remain);                   if (valid && remain<0)                    // offer count is more than need, quit this offer                    valid = false;            }            if (valid)                 // recurse calculate the remaining needs                result = Math.min(result, shoppingOffers(price, special, needs)+offer.get(needs.size()));            for (int j=0; j<needs.size(); j++) {                // add back to needs                int origin = needs.get(j)+offer.get(j);                needs.set(j, origin);            }        }                // then calculate price with non offer, and choose the smaller one return        int nonOffer = 0;        for (int i=0; i<needs.size(); i++) {            nonOffer += price.get(i) * needs.get(i);        }        return Math.min(result, nonOffer);    }}





原创粉丝点击