【问题标题】:Why does this code work for this TopCoder prob?为什么此代码适用于此 TopCoder 问题?
【发布时间】:2012-05-08 12:05:12
【问题描述】:

我从 HOURS 开始就一直在思考这个 TopCoder 问题,但无法找到完美的解决方案,但发现下面给出的解决方案非常漂亮!

我试图弄清楚这个解决方案如何适用于给定的探针?而我当初怎么会想到呢?在阅读了解决方案后,我认为它是霍夫曼编码的一种变体,但这是我所能得到的。我真的很着迷,想知道什么样的思路可以导致这个解决方案..

问题来了: http://community.topcoder.com/stat?c=problem_statement&pm=11860&rd=15091

Fox Ciel 有很多功课要做。作业包括一些 相互独立的任务。不同的任务可能需要不同的金额 的时间来完成。您将获得一个 int[] workCost。对于每个 i, 第 i 个任务需要 workCost[i] 秒才能完成。她愿意 参加一个聚会并见她的朋友,因此她想完成所有 尽快完成任务。

主要问题是所有的狐狸,包括夏尔,真的很讨厌做 在家工作。每只狐狸只愿意做其中一项任务。幸运的是, 哆啦A梦,22世纪的机器猫,与Fox Ciel分道扬镳 锤子:可以将任何一只狐狸一分为二的魔法道具。

给你一个 int splitCost。在狐狸身上使用劈锤是 瞬间。一旦锤子用在狐狸身上,狐狸就会开始 分裂。 splitCost 秒后她会变成两只狐狸—— 原来的狐狸和另一只全新的狐狸。当狐狸分裂时, 不允许再对她使用锤子。

一项任务的工作不能被打断:一旦狐狸开始工作 一项任务,她必须完成。不允许多只狐狸 合作完成同一任务。狐狸不能在她做任务的时候工作 用锤子劈开。可以分裂同一个狐狸 多次。之前和之后都可以分裂狐狸 她解决了其中一项任务。

计算并返回狐狸可以用的最短时间 解决所有任务。

这是我在link找到的解决方案

import java.util.*; 

public class FoxAndDoraemon { 
  public int minTime(int[] workCost, int splitCost) { 
    PriorityQueue<Integer> pq = new PriorityQueue<Integer>(); 

    for(int i : workCost) pq.offer(i); 

    while(pq.size()>=2) { 
      int i = pq.poll(); 
      int j = pq.poll(); 
      pq.offer(Math.max(i, j) + splitCost); 
    } 
    return pq.poll(); 

  } 
}

【问题讨论】:

  • 轮询时优先级队列是返回最大元素还是最小元素?
  • 最少。优先级队列从最小到最大元素排序,并在插入时保留它们的排序。
  • 这个答案似乎不正确。考虑minTime(new int[] {1, 1, 1}, 5)。显然正确的做法是不并行化任何任务,这样就需要 3s。这个解决方案会给 11 秒!
  • @RussellZahniser 每只狐狸只会做一项工作。您不能让它连续执行 3 个作业。 `每只狐狸只愿意做其中一项任务'

标签: java algorithm huffman-code


【解决方案1】:

首先,您确实了解“max(i, j) + splitCost”背后的原因。不是吗?基本上,如果您有一只狐狸,您可以将其分成两部分并独立执行每项任务。让我们称这个过程为“合并”。

现在假设我们有三个工作 a、b 和 c,使得 a>b>c。您可以执行合并(合并(a,b),c)或合并(合并(a,c),b)或合并(合并(b,c),a)。算一算,你可以证明 merge(merge(b,c),a) 在这三者中最少。

您现在可以使用归纳法来证明此解决方案适用于任意数量的工作(不仅仅是 3 个)。

【讨论】:

    【解决方案2】:

    它正在从头开始建造一棵树。

    该算法使用一个基本事实来工作: 如果删除两个最小元素,计算最小元素的成本始终小于下一个最小元素的成本加上拆分。 (请参阅 ElKamina 的帖子以获得更全面的证明)。

    因此,如果您的树中只有两个元素(例如 4 和 2)并且您的拆分成本为 4,那么最短的时间量始终为 8(下一个最小的元素加上拆分成本。

    所以,构建我们的树:假设我们得到了 workCost [1,3,4,5,7,8,9,10],我们的 splitCost 是 3。

    所以,我们来看两个最小的元素:1,3。计算这些的“成本”至少为 6(最大数字加上拆分成本。然后将 6 重新插入队列中,您实际上是在添加子树:

      6
    1   3
    

    “高度”/“成本”总共为 6。通过重复此过程,您将使用尽可能小的子元素构建一棵树(现有的子树或未完成的新作业)。

    解决方案最终将如下所示:(其中 S(X) 是拆分成本加上解决它下面的所有问题)

                      S(17)
                S(13)       S(14)
           S(10)     9   10      S(11)
      S(6)      7            S(8)     8
    1     3                 4    5
    

    如果你向后追溯这棵树,很容易看出公式是如何解决它的:1 和 3 的成本是 S(6),4 和 5 是 S(8),那么 S(6) 和 7 是S(10), 8 和 S(8) 是 S(11) 等等。

    【讨论】:

      猜你喜欢
      • 2015-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 2019-08-28
      • 1970-01-01
      • 1970-01-01
      • 2016-08-03
      相关资源
      最近更新 更多