从立方体建造塔

时间:2013-11-16 15:19:33

标签: algorithm

你可以用立方体制作稳定的塔,不要把它放得更小,而不能把它放得更重一些。

编写一个程序,从N个立方体中为您提供最高的塔。

输入txt的第一行包含多维数据集的数量。 (1< = n< = 100)在以下N行中,有立方体的长度和重量。

示例:

Input.txt       Output.txt (from bottom to top)
5               3
10 3            20 5
20 5            10 3
15 6            10 2
15 1
10 2

内存限制:16 mb运行时间:0.2秒

你能帮助我吗?

3 个答案:

答案 0 :(得分:1)

有不同的方法可以解决这个问题。这是天真的方式,在伪代码中效率相当低:

// `Input` is a list of `Cube` who have a `Size` and `Weight` property

int largestStack(input_cubes_left, currentCube)
{
   max = 0 // at worst, there are no cubes that fit on top of currentCube
   foreach (cube in input_cubes_left)
   {
      // skip all cubes which don't fit
      if (cube.Size <= current.Size and cube.Weight <= current.Weight)
      {

        // measure the stack with currentCube, this cube, and whatever is left
        size = 1 + largestStack(input_cubes_without_cube, cube)

        // but of course we only count the ones 
        // which are bigger than our best result
        if size>max 
          max = size
      }
   }
   return max;
}

当然,这是一种简化的解决方案,可以检查所有可能的组合(N阶乘!)。 以下是一些让您开始优化它的问题:

  • 如何利用排序来避免检查大量无效组合?
  • 如何利用Linq在功能上解决这个问题?

答案 1 :(得分:1)

算法

我想出的算法通过使用有序对的列表来工作。这些对首先按一个元素排序,然后按第二个排序。

我们维护对的列表,其中每个新对都是:

  • 添加到最高列表的末尾,如果它可以放在最后一个元素之后
  • 添加到新列表的末尾,该列表是在其中一个现有列表中找到的最高段的副本,可以附加到该列表
  • 如果无法放入现有列表中的任何位置,则会添加到新列表中。

证明

  1. 第一个元素将进入一个新列表,这将是最高的。
  2. n -th元素将转到最高列表(或列表段)的末尾,使其成为该元素的最高列表。
  3. n 之后的第一个元素,元素 k ,可以使用 n 将附加到包含 n 的最高列表,因为2.如果某个更高的列表存在,则元素<可以附加 k 元素的strong> i ,然后将规则2应用于元素 i 即可。这使得带有 k 的列表成为该元素的最高列表。
  4. 通过归纳,这证明了算法的概念。


    伪代码

    foreach ordered pair
        maximumIndex <- 0
        maximumList <- null
        foreach list
            highest, length <- FindLongestPath(list, pair)
            if highest > maximumHeight
                maximumHeight<- highest 
                maximumIndex <- lenght
                maximumList <- list
        if maximumIndex = 0
            lists.add(new list{pair});
        else if maximumIndex < maximumList.Length
            lists.add(new list{maximumList[0..maximumIndex - 1] + pair});
        else
            list.add{pair};
    

    FindLongestPath方法在列表中搜索该对可以容纳的第一个位置,并使用它返回该段的高度。通过简单的应用程序(从开始到找到位置for),我估计在最坏的情况下算法的复杂度为O(N ^ 2)。

    如果实现为二进制搜索,我猜想复杂度为O(N log N),但是对于N <= 100,它并不重要。


    实际代码

    由于没有人喜欢破译其他人的伪代码,这里是在pastebin上实际运行的C#代码:http://pastebin.com/3vLn343j

    文件“Input.txt”(在问题中格式化)应与可执行文件位于同一目录中(在Visual Studio中,您可以将其放在解决方案根目录中,并在属性集“复制到输出”中设置为'复制如果更新')。

答案 2 :(得分:1)

首先,让我们假设没有相等的立方体(具有相同长度/重量的立方体),按照以下定义构建一个有向图:

  1. 图表中每个多维数据集的一个节点
  2. 如果立方体B可以放在立方体A上,则添加边缘(A - > B)
  3. 很容易知道这是一个DAG(http://en.wikipedia.org/wiki/Directed_acyclic_graph

    原始问题等于在DAG中找到最长路径。我们可以使用动态编程来解决这个问题。

    回到假设,即使考虑相同的立方体,我们也可以稍微改变以覆盖相等的立方体。 (每个节点都有属性 - equalCount,等于立方体的数量。并将最长路径定义更新为沿路径的equalCount之和,以替换原始定义:沿路径的节点数)