ZOJ 1093 Monkey and Banana (LIS)解题报告

ZOJ  1093   Monkey and Banana  (LIS)解题报告

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87125#problem/B

题目:

Description

一组研究人员正在设计一项实验,以测试猴子的智商。他们将挂香蕉在建筑物的屋顶,同时,提供一些砖块给这些猴子。如果猴子足够聪明,它应当能够通过合理的放置一些砖块建立一个塔,并爬上去吃他们最喜欢的香蕉。
 
研究人员有n种类型的砖块,每种类型的砖块都有无限个。第i块砖块的长宽高分别用xi,yi,zi来表示。 同时,由于砖块是可以旋转的,每个砖块的3条边可以组成6种不同的长宽高。
 
在构建塔时,当且仅当A砖块的长和宽都分别小于B砖块的长和宽时,A砖块才能放到B砖块的上面,因为必须留有一些空间让猴子来踩。
 
你的任务是编写一个程序,计算猴子们最高可以堆出的砖块们的高度。

Input

输入文件包含多组测试数据。
  每个测试用例的第一行包含一个整数n,代表不同种类的砖块数目。n<=30.
接下来n行,每行3个数,分别表示砖块的长宽高。
当n=  0的时候,无需输出任何答案,测试结束。

Output

对于每组测试数据,输出最大高度。格式:Case  第几组数据: maximum 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 

Sample Output

Case 1: maximum height = 40 
Case 2: maximum height = 21   
Case 3: maximum height = 28   
Case 4: maximum height = 342
 
题目大意:
有N块已知长、宽、高的砖,每种砖的数量不限,将砖摞起来,使在上面的砖的长宽都小于下面的(不能等于),求能堆成的最大高度。
 
分析:
LIS问题。动态规划dp。
由于砖块可以旋转,那么给一块砖就相当于给了三块砖(即N<=30*3)。
求从编号 i 出发能堆出的最大高度(不包括砖块),dp(i) = max(dp(j) + j的高度; j是能放在i上面的砖块编号),将开始节点看成地板最大高度为无穷大,为dp(0);
 
代码:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<climits>  //用INT_MAX
 4 using namespace std;
 5 const int M=100;
 6 
 7 int box[M][3];
 8 int height[M];
 9 int number;
10 
11 //互换长宽高,转换砖块的三种类型
12 void change(int index,int a,int b,int c)
13 {
14     box[index][0]=a;
15     box[index][1]=b;
16     box[index][2]=c;
17 }
18 
19 int dp(int j)
20 {
21     int& ans=height[j];
22     if(ans!=-1)  //搜索过的直接返回
23         return ans;
24     for(int i=1;i<=number;i++)//搜索每一层
25     {
26         if(i!=j)
27         {
28             if((box[i][0]<box[j][0]&&box[i][1]<box[j][1])||(box[i][1]<box[j][0]&&box[i][0]<box[j][1]))
29             {
30                 int temp=dp(i)+box[i][2];
31                 if(temp>ans)
32                     ans=temp;
33             }
34         }
35     }
36     if(ans==-1)//最后一层未更新
37         ans=0;
38     return ans;
39 }
40 
41 int main()
42 {
43     int n;
44     int m=1;
45     while(scanf("%d",&n)&&n)
46     {
47         int a,b,c;
48         number=0;
49         box[0][0]=box[0][1]=box[0][2]=INT_MAX;//地板看成无穷大砖块
50         for(int i=1;i<=n;i++)
51         {
52             scanf("%d%d%d",&a,&b,&c);
53             change(++number,a,b,c);
54             change(++number,b,c,a);
55             change(++number,c,a,b);
56         }
57         for(int i=0;i<=number;i++)
58         {
59             height[i]=-1;
60         }
61         printf("Case %d: maximum height = %d
",m++,dp(0));
62     }
63     return 0;
64 }

每次都想完全自己写,可是自己写的都有很多错误,最后有看了别人的博客。

 
原文地址:https://www.cnblogs.com/ttmj865/p/4725505.html