#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=200;
struct Block{
int x,y,high;
int dp;//该箱子在最下面时的最大高度
bool operator <(const Block &u)const{
if(x<u.x) return 1;
else if(x==u.x&&y<u.y) return 1;
else return 0;
}
}block[maxn];
int main()
{
int n;
int cnt=1;
int a,b,c,k;
while(~scanf("%d",&n)!=EOF&&n)
{
k=0;
while(n--)
{
scanf("%d%d%d",&a,&b,&c);
if(a==b&&b==c)
{
block[k].x=a,block[k].y=b,block[k].high=c;block[k].dp=block[k].high;k++;
}
else if(a==b&&a!=c)
{
block[k].x=a,block[k].y=b,block[k].high=c;block[k].dp=block[k].high;k++;
block[k].x=a,block[k].y=c,block[k].high=b;block[k].dp=block[k].high;k++;
block[k].x=c,block[k].y=a,block[k].high=b;block[k].dp=block[k].high;k++;
}
else if(a==c&&a!=b)
{
block[k].x=a,block[k].y=c,block[k].high=b;block[k].dp=block[k].high;k++;
block[k].x=a,block[k].y=b,block[k].high=c;block[k].dp=block[k].high;k++;
block[k].x=b,block[k].y=a,block[k].high=c;block[k].dp=block[k].high;k++;
}
else if(b==c&&b!=a)
{
block[k].x=b,block[k].y=c,block[k].high=a;block[k].dp=block[k].high;k++;
block[k].x=b,block[k].y=a,block[k].high=c;block[k].dp=block[k].high;k++;
block[k].x=a,block[k].y=b,block[k].high=c;block[k].dp=block[k].high;k++;
}
else
{
block[k].x=a,block[k].y=b,block[k].high=c;block[k].dp=block[k].high;k++;
block[k].x=a,block[k].y=c,block[k].high=b;block[k].dp=block[k].high;k++;
block[k].x=b,block[k].y=a,block[k].high=c;block[k].dp=block[k].high;k++;
block[k].x=b,block[k].y=c,block[k].high=a;block[k].dp=block[k].high;k++;
block[k].x=c,block[k].y=a,block[k].high=b;block[k].dp=block[k].high;k++;
block[k].x=c,block[k].y=b,block[k].high=a;block[k].dp=block[k].high;k++;
}
}
sort(block,block+k);
int ans=-1;
//每个block[i]为当前最底层
for(int i=1;i<k;i++)
{
for(int j=0;j<i;j++)
{
if(block[i].x>block[j].x&&block[i].y>block[j].y)
block[i].dp=max(block[j].dp+block[i].high,block[i].dp);
}
if(block[i].dp>ans)
ans=block[i].dp;
}
printf("Case %d: maximum height = %d\n",cnt++,ans);
}
return 0;