盒子塔

时间:2018-11-26 20:08:23

标签: java algorithm recursion

我们有N个框。每个盒子都有3个参数:宽度,长度,高度。

我需要编写一个函数,使用此框生成最高的塔。 函数必须遵守以下规则:底部框的所有参数都应大于其上方的框。

示例

假设我们有一个描述为int数组{width, length, height} -> {1, 2, 5}的框,然后:

输入:boxes = {{2, 2, 3}, {1, 1, 1}, {3, 3, 3}, {4, 5, 4}, {7, 7, 1}}

输出:8{4, 5, 4} greater than {2, 2, 3} greater than {1, 1, 1}

解决方案

我找到了一种我不明白的解决方案。

void sortArrDesc(int[][] array) {
  Arrays.sort(array, new java.util.Comparator<int[]>() {
    public int compare(int[] a, int[] b) {
      return -1 * Integer.compare(a[2], b[2]);
    }
  });
}

boolean canPlaceOnTop(int prevBoxIndex, int currBoxIndex, int[][] boxes) {
  if (prevBoxIndex == -1) return true;
  int[] bottomBox = boxes[prevBoxIndex];
  int[] topBox = boxes[currBoxIndex];

  return (bottomBox[0] > topBox[0] && 
          bottomBox[1] > topBox[1] && 
          bottomBox[2] > topBox[2]);
}

int getHighestTower(int prevBoxIndex, int currBoxIndex, int[][] boxes) {
  if (currBoxIndex == boxes.length) return 0;

  int nextBoxIndex = currBoxIndex + 1;

  int heightWithCurrBox = 0;

  if (canPlaceOnTop(prevBoxIndex, currBoxIndex, boxes)) { 
    int currentBoxHeight = boxes[currBoxIndex][2];
    int heightNextBox = getHighestTower(currBoxIndex, nextBoxIndex, boxes);
    heightWithCurrBox = heightNextBox + currentBoxHeight;
  }

  int heightWithoutCurrBox = 
            getHighestTower(prevBoxIndex, nextBoxIndex, boxes);


  return Math.max(heightWithCurrBox, heightWithoutCurrBox);
}

int getHighestTower(int[][] boxes) {
  sortArrDesc(boxes);
  return getHighestTower(-1, 0, boxes);
}

我不知道getHighestTower函数到底能做什么。

我的意思是,例如,当我调用函数Math.sqrt(5)时,我知道我的平方根为5。但是在这里,在getHighestTower函数中发生了奇怪的事情。

很明显,呼叫getHighestTower(-1, 0, boxes)将返回最高的塔。

但是!当我们进行递归调用时,我不明白它们的含义。 getHighestTower(prevBoxIndex, nextBoxIndex, boxes)

这行是什么意思?

该调用似乎应该从nextBox返回最大可能的高度,但是为什么我们需要使用prevBoxIndex

此外,此调用getHighestTower(currBoxIndex, nextBoxIndex, boxes);看起来也一样,但是我们使用prevBoxIndex而不是currBoxIndex,为什么呢?

P.S。我已经找到了这个question,但是其中没有任何有用的信息。

1 个答案:

答案 0 :(得分:0)

这个问题可以这样解决:

  1. 按高度对框进行排序。

  2. 然后的问题是寻找高度总和最大的递增子序列-这里的“递增”表示:

currLength > prevLength && currWidth > prevWidth && currHeight > prevHeight

对于输入{{2, 2, 3}, {1, 1, 1}, {3, 3, 3}, {4, 5, 4}, {7, 7, 1}}

让我们说按高度数组排序的是:

{7,7,1}, {1,1,1}, {2,2,3}, {3,3,3}, {4,5,4}

则具有上述标准的递增子序列为

{1,1,1}, {3,3,3}, {4,5,4}

那么高度为1 + 3 + 4 = 8

为什么首先需要按高度排序? 因为,假设输入为

{{4,5,4}, {2,2,3}, {1,1,1}, {3,3,3}, {7,7,1}}

并且不按高度排序,则按上述标准增加的子序列将产生

{1,1,1}, {3,3,3}

它给出的答案为1 + 3 = 4,这不是最佳选择。

Java代码:

 private static int getHeighestTower( int[][] x ) {
    Arrays.sort( x, new Comparator<int[]>() {
      @Override
      public int compare( int[] a, int[] b ) {
        return a[2] - b[2];
      }
    });

    int[] L = new int[x.length];
    Arrays.fill(L,1);
    int max = 0;
    int h = 0;
    int hi = 0;
    for ( int i = 0; i < x.length; i++ ) {
      hi = x[i][2];
      int lastAdded = 0;
      for ( int j = 0; j < i; j++ ) {
        if ( aBiggerThanB(x[i], x[j]) ) {
          if ( L[i] < 1 + L[j] ) {
            L[i] = 1 + L[j];
            hi += x[j][2];
            lastAdded = x[j][2];
          } else if ( L[i] == 1 + L[j] ) {
            hi = Math.max( hi, hi - lastAdded + x[j][2]);
          }
        }
      }
      h = Math.max( h, hi);
      max = Math.max( max, L[i] );
    }

    return h;
 }

 private static boolean aBiggerThanB( int[] a, int[] b ) {
    return a[0] > b[0] && a[1] > b[1] && a[2] > b[2];
 }