zju1093 monkey and banana 猴子和香蕉

有一班科学家正在设计一个测试猴子IQ的试验。他们把一只“banana”吊在天花板,而且同时给猴子一些箱子。如果猴子聪明的话,它们会把箱子一个个叠起来做成一个塔子来取得食物。科学家有n种箱子,而且每一种箱子都有好多个。第 i 种箱子有三维(xi,yi,zi)。箱子可以用它的任意一面作底面来摆放,也就是它的三维之中可以任选两条来做它的底面长和宽。科学家想确定箱子叠到最高的时候是可以到达天花板的。现在问题是,要叠起一个塔子,上下摆放的两个箱子,在上的箱子的底面长宽必须严格小于在下的箱子的底面长宽,留下些地方让猴子落脚来爬上去。也就是说,底面面积相等的箱子不能叠放。现在你的任务是利用所给定的箱子,决定塔子最高能达到的高度输入方式:
输入数据有多组测试数据。
每一组测试数据的第一行是一个整数n,表示不同三维的箱子的总数。n最大为30。
以下的n行每一行有三个正整数,表示该箱子的三维xi,yi和zi。
当n=0的时候输入结束。输出方式:

对应每组测试数据,输出一行包括数据组号case(从1开始)和塔子最高高度height,并按照一下格式: "Case case: maximum height = height" 


每个箱子有六个面,只有三种面,所以每个箱子我们可分成3中箱子,然后将箱子的横坐标排序即可。类似于dp求最长子序列。

code:

 

var
  x,y,f,z:array[0..180] of longint;
  n,ans,zzb:longint;

  procedure qsort(L,r:Longint);
  var i,j,m,t,mm:Longint;
  begin
    i:=l; j:=r; m:=x[(i+j) div 2]; mm:=y[(i+j) div 2];
    repeat
     while (x[i]>m) or ((x[i]=m) and (y[i]>mm)) do inc(i);
     while (x[j]<m) or ((x[j]=m) and (y[j]<mm)) do dec(j);
     if i<=j then
     begin
       t:=x[i]; x[i]:=x[j]; x[j]:=t;
       t:=y[i]; y[i]:=y[j]; y[j]:=t;
       t:=z[i]; z[i]:=z[j]; z[j]:=t;
       inc(i); dec(j);
     end;
    until i>j;
    if l<j then qsort(l,j);
    if i<r then qsort(i,r);
  end;

  function max(a,b:longint):longint;
  begin if a>b then exit(a); exit(b); end;

  procedure init;
  var i,j,k,a,b,c:longint;
  begin
   readln(n); zzb:=0;
   while n<>0 do
   begin
   inc(zzb);
   fillchar(f,sizeof(f),0);  ans:=0;
   for i:=1 to n do
   begin
    readln(a,b,c);
    x[i*6-5]:=b; y[i*6-5]:=a; z[i*6-5]:=c;
    x[i*6-4]:=c; y[i*6-4]:=b; z[i*6-4]:=a;
    x[i*6-3]:=a; y[i*6-3]:=c; z[i*6-3]:=b;
    x[i*6-2]:=a; y[i*6-2]:=b; z[i*6-2]:=c;
    x[i*6-1]:=b; y[i*6-1]:=c; z[i*6-1]:=a;
    x[i*6]:=c;   y[i*6]:=a;   z[i*6]:=b;
   end;
   n:=6*n;
   qsort(1,n);
   f[1]:=z[1];
   for i:=2 to n do
   begin
     for j:=1 to i-1 do
     if ((x[i]<x[j]) and (y[i]<y[j])) then
      f[i]:=max(f[i],f[j]);
      f[i]:=f[i]+z[i];
      ans:=max(ans,f[i]);
   end;
    writeln('Case ',zzb,': maximum height = ',ans);
   readln(n);
  end;
  end;
begin
 init;
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值