Chapter06-Monkey and Banana(EOJ 1093)

通过排列组合不同尺寸的长方体盒子以搭建最高塔,解决猴子够取屋顶香蕉的问题。运用最长递增子序列算法思想,考虑长宽约束条件实现动态规划。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Monkey and Banana


Time Limit: 2 Seconds      Memory Limit: 65536 KB


A group of researchers are designing anexperiment to test the IQ of a monkey. They will hang a banana at the roof of abuilding, and at the mean time, provide the monkey with some blocks. If themonkey is clever enough, it shall be able to reach the banana by placing oneblock on the top another to build a tower and climb up to get its favoritefood.

The researchers have n typesof blocks, and an unlimited supply of blocks of each type. Each type-i blockwas a rectangular solid with linear dimensions (xi, yi,zi). A block could be reoriented so that any two of its threedimensions determined the dimensions of the base and the other dimension wasthe height.

They want to make sure that the tallesttower possible by stacking blocks can reach the roof. The problem is that, inbuilding a tower, one block could only be placed on top of another block aslong as the two base dimensions of the upper block were both strictly smallerthan the corresponding base dimensions of the lower block because there has tobe some space for the monkey to step on. This meant, for example, that blocksoriented to have equal-sized bases couldn't be stacked.

Your job is to write a program thatdetermines the height of the tallest tower the monkey can build with a givenset of blocks.

InputSpecification

The input file willcontain one or more test cases. The first line of each test case contains aninteger n,
representing the number of different blocks inthe following data set. The maximum value for n is 30.
Each of the next n linescontains three integers representing the values xiyi and zi.
Input is terminated by a value of zero (0) for n.

OutputSpecification

For each test case, printone line containing the case number (they are numbered sequentially startingfrom 1) and the height of the tallest possible tower in the format"Case case: maximum height = height"

Sample Input

1

10 20 30

2

6 8 10

5 5 5

7

1 1 1

2 2 2

3 3 3

4 4 4

5 5 5

6 6 6

7 7 7

5

31 41 59

26 53 58

97 93 23

84 62 64

33 83 27

0

Sample Output

Case 1: maximumheight = 40

Case 2: maximumheight = 21

Case 3: maximumheight = 28

Case 4: maximumheight = 342


Source: Universityof Ulm Local Contest 1996

 

 

 

题目大意:

       为了测试猴子的ID,提供了多种小箱子(长方体);每种长方体无限个,也可以任意摆放;

       求出叠加这些箱子能够达到的最高高度;能够叠加的要求是:下边的箱子的长和宽必须同时大于上边箱子的长和宽;

 

分析:

       原理和最长递增子序列基本一样,如果不清楚最长递增子序列的工作流程不妨看博客http://blog.youkuaiyun.com/haizi8888/article/details/23713995

 

两点需要注意:

1,如何排序?

   不妨以从小到大排序,(这个无所谓),按照哪条边排序呢?按底边的最短边排序或者底边的最长边排序都可以;

2,注意初始化数组height。

   因为对于数组的每一位的最小值都应该为该位置的方块的高度,所以初始化的时候不能对数组的每一位分别赋值;

 

java代码:

 

import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
 
public classMain {
   private Node[] block;
   private int[] height;
 
   public Main(int len) {
      block = new Node[len];
      height = new int[len];
   }
 
   public static void main(String[] args) {
      // TODO Auto-generated method stub
      Scannercin = newScanner(newBufferedInputStream(System.in));
      int n;
      Mainma;
      int x, y, z;
      int count = 1;
      while ((n = cin.nextInt()) !=0) {
        ma= newMain(3 * n);
        for (int i = 0; i < 3 *n;i++) {
           x= cin.nextInt();
           y= cin.nextInt();
           z= cin.nextInt();
 
           ma.block[i] = new Node(Math.max(x,y), Math.min(x, y), z);
           ma.block[++i] = new Node(Math.max(x,z), Math.min(x, z), y);
           ma.block[++i] = new Node(Math.max(y,z), Math.min(y, z), x);
          
        }
        System.out.print("Case "+count+":"+" maximum height = ");
        System.out.println(ma.getMaxHeight());
        count++;
      }
   }
 
   private int getMaxHeight() {
      // TODO Auto-generated method stub
      int maxheight = 0;
      Arrays.sort(block);
     
      for(int i = 0;i<height.length;i++){ 
        height[i] = block[i].z;
      }
     
      for(int i = block.length -2;i>=0;i--){                                                                                                                    
        for(int j = i+1;j<block.length;j++){
           if(block[i].x > block[j].x && block[i].y > block[j].y ){
              height[i] = Math.max(height[i], height[j]+block[i].z);
           }
        }
      }
     
      for(int i = 0;i<height.length;i++){
        maxheight= Math.max(maxheight,height[i]);
      }
     
      return maxheight;
   }
 
   // 将最大边作为x
   static class Node implementsComparable<Node> {
      private int x, y, z;
 
      public Node(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
      }
      //倒叙
      @Override
      public int compareTo(Node o) {
        // TODO Auto-generated method stub
        //以最长的边来排序;
        if (x > o.x) {
           return -1;
        }elseif(x < o.x) {
           return 1;
        }
       
        if (y > o.y) {
           return -1;
        }elseif(y < o.y) {
           return 1;
        }
       
        return 0;
      }
   }
}
 







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值