【问题标题】:Topcoder SRM 149 D2 Q3: PricingTopcoder SRM 149 D2 Q3:定价
【发布时间】:2016-05-21 18:33:59
【问题描述】:

以下问题取自 Topcoder 的 SRM 149。即使查看了解决方案,我也不知道该怎么做。我一直在尝试这个问题一个半小时,并从解决方案开始又一个小时,但我就是无法理解它在做什么......

如果有人能给我一些关于此解决方案如何工作的提示,我将不胜感激。

问题:http://topcoder.bgcoder.com/print.php?id=250

解决方案:http://apps.topcoder.com/forums//?module=Thread&threadID=575120&start=0

SRM 149(Division II 三级)中使用的 TopCoder 问题“定价”

问题陈述 最简单形式的市场差异化是对同一产品的不同客户收取不同价格的系统。为了使总销售收入最大化,我们希望单独向每个客​​户收费,收取该客户愿意支付的最高价格。通常我们必须将客户分成几组,对一个组中的每个人收取相同的价格(例如商务舱、经济舱等)。 我们列出了我们产品的所有潜在客户以及每个客户愿意支付的最高金额。我们决定将它们分成四个或更少(不重叠)的组。每个组内的每个人都将获得相同的价格。我们的目标是选择最优的组和价格,以最大化我们的总销售收入。

创建一个包含方法 maxSales 的 Pricing 类,该方法采用 int[] price 包含每个潜在客户愿意支付的最高价格,并返回我们可以通过将客户分为四个或更少的组来产生的最大销售收入.

定义

类:定价 方法:maxSales 参数:int[] 返回:整数 方法签名:int maxSales(int[] price) (确保你的方法是公开的)

约束

  • 价格必须包含 1 到 50 个元素(含)
  • 价格的每个元素必须在 0 到 1000 之间(含)

例子

0)

{9,1,5,5,5,5,4,8,80} 回报:120 向愿意支付 80 的一位客户收取 80。 向愿意支付 8 或 9 的 2 位客户收取 8。 向愿意支付 5 的 4 位客户收取 5。 向愿意支付 4 的一位客户收取 4。 总销售收入 = 1*80 + 2*8 + 4*5 + 1*4。 (我们可以将愿意支付 1 的客户放入这些组中的任何一个,因为他不会以这些价格购买任何东西。) 1)

{17,50,2} 回报:69 我们只使用三个组,每个组包含一个客户。我们向每位顾客收取她愿意支付的最高费用。总销售收入 = 1*17 + 1*50 + 1*2 2)

{130,110,90,13,6,5,4,3,0} 回报:346 向愿意在 4 到 13 之间支付的 4 个客户中的每一个收取 4 的价格,从而从他们那里得到总共 16 个。然后向愿意支付很多费用的三个客户中的每一个收取我们所能支付的最高费用。 4*4 + 90 + 110 + 130 = 346

SOLUTION:
Arrays.sort(price);
   int ret = 0;
   for(int i = 0; i<price.length; i++){
      for(int j = i; j<price.length; j++){
         for(int k = j; k<price.length; k++){
            for(int m = k; m<price.length; m++){
               int rev = 0;
               for(int n = 0; n<price.length; n++){
                  if(price[n]>=price[m]){
                     rev+=price[m];
                  }else if(price[n]>=price[k]){
                     rev+=price[k];
                  }else if(price[n]>=price[j]){
                     rev+=price[j];
                  }else if(price[n]>=price[i]){
                     rev+=price[i];
                  }
               }
               ret=Math.max(ret,rev);
            }
         }
      }
   }
   return ret;

【问题讨论】:

    标签: c++ algorithm


    【解决方案1】:

    这是蛮力。

    每组 {i,j,k,m} 是四个组的价格选择。 n 循环计算该选择的收入,ret 跟踪最大收入。

    (这个解决方案是O(N5)。我认为O(N)是可能的。)

    【讨论】:

    • 确实,在我们有 k 个或更少组的一般情况下,有一个 O(kn) 时间的 DP 算法(所以如果 k 是一个常数 (4),这将是 O(n) ):按升序对价格进行排序,令 f(i, j) 为将前 i 个价格分成至多 j 个组所能达到的最大总和。那么 f(i, 0) = 0,并且 f(i, j >= 1) = max(price[h] * (i-h+1) + f(h-1, j-1)) 超过所有 1
    • 是的,我了解这些部分。但我的主要困惑是:为什么他们需要 4 个迭代器?我无法弄清楚它是如何将这些数字放入“4 个桶”的......
    • @Telenoobies:你需要多少迭代器才能对 {i,j,k,m} 进行暴力搜索?最内层循环内的代码将数字 price[n] 放入四个“桶”之一(或无)。
    • 就是这样,我不明白这 4 个嵌套循环是如何将它们放入 4 个桶中的……这非常令人沮丧。这似乎也是一个简单的问题。
    • @Telenoobies:查看最内层循环中的代码。ijkmn 作为常量,看看这段代码做了什么。
    【解决方案2】:

    我想我会分享我的解决方案,尽管它是一种痛苦且令人困惑的蛮力(正如 Beta 所建议的那样)。我使用itertools 来获取定价组合而不是嵌套循环——这感觉更合乎逻辑,因为我明确指定了可能的组大小(请参阅range(0, MAX_GROUPS))。

    注意我只在 Topcoder Arena 的基本测试用例上测试过这个,而不是 SRM 149 中的所有测试用例。最终的修剪代码是 hacky。

    import itertools
    
    MAX_GROUPS = 4
    
    # price ~ (int, int, ...)
    def maxSales(price):
    
        # Returns from given sales combination
        def _ret(grp):
            return sum([len(g) * g[0] for g in grp])
    
        if len(price) <= MAX_GROUPS:
            return sum(price)
    
        # Sort price listing ascending, and then split into 1-4 groups
        price = sorted(price)
        grp_max_ret, grp = -1, []
        for i in range(0, MAX_GROUPS):
            for splits in itertools.combinations(range(1, len(price)), i):
                result = []
                prev = None
                for split in itertools.chain(splits, [None]):
                    result.append(list(price[prev:split]))
                    prev = split
                result_ret = _ret(result)
                # Keep track of top performer
                if result_ret > grp_max_ret:
                    grp_max_ret, grp = result_ret, result
    
        # Trim first group, which effectively gives freebies
        pre_trim_grp = grp[:]
        for _ in range(len(pre_trim_grp[0])-1):
            trim_grp = pre_trim_grp[:]
            trim_grp[0].pop(0)
            grp_max_ret = max(grp_max_ret, _ret(trim_grp))
    
        return grp_max_ret
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多