解法一:把每个方块,当成3个点,地面设为p[0] 点,有向图的 最长路,用 floyd 水过
其实应该用 dp 做的。。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
int n,i,j,k;
struct node{
int a,b,len;
}p[100];
int map[100][100];
int main()
{
int t=0;
while(scanf("%d",&n),n){
t++;
int ans=1,x,y,z;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);//一个方块 相当于 3个点
p[ans].a=x;
p[ans].b=y;
p[ans++].len=z;
p[ans].a=x;
p[ans].b=z;
p[ans++].len=y;
p[ans].a=z;
p[ans].b=y;
p[ans++].len=x;
}
p[0].a=9999999; // 地面 每个点 都能到,所以赋值为 最大
p[0].b=9999999;
p[0].len=0;
for(i=0;i<ans;i++)
for(j=0;j<ans;j++)
map[i][j]=-9999999; //将map 都赋值为 最小
for(i=0;i<ans;i++)
for(j=0;j<ans;j++)
if((p[i].a>p[j].a&&p[i].b>p[j].b) || (p[i].a>p[j].b&&p[i].b>p[j].a))
map[i][j]=p[j].len; //满足条件,i点到j点的 距离就为 j的 长度
for(k=0;k<ans;k++)
for(i=0;i<ans;i++)
for(j=0;j<ans;j++)
if(map[i][k]+map[k][j]>map[i][j])
map[i][j]=map[i][k]+map[k][j];//floyd 算法 水过
int max=-1;
for(i=0;i<ans;i++)
if(map[0][i]>max)
max=map[0][i]; //挑出最大的长度
printf("Case %d: maximum height = %d\n",t,max);
}
}
解法二:
哈哈,研究了一下dp的做法,做出来了
解析:就是将所有 方块按 面积 (从小到大)排序。之后,小面积的方块一定不能 覆盖 大面积的方块,大面积的方块可能 覆盖小面积的方块。
问题就变成了,和求 最长上升子序列 差不多。
最长上升子序列:3 6 4 8 2 -1 9 4
前面的数一定不能 覆盖 后面的数,但后面的数 可能 覆盖 前面的数(如果后面的数>前面的数,就可以排在那个数的后面)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
int n,i,j,k;
int dp[100];
struct node{
int a,b,len,s;
}p[100];
bool comp(node a,node b)
{
return a.s<b.s;
}
int main()
{
int t=0;
while(scanf("%d",&n),n){
t++;
int ans=1,x,y,z;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);//一个方块 相当于 3个点
p[ans].a=x;
p[ans].b=y;
p[ans].s=x*y;
p[ans++].len=z;
p[ans].a=x;
p[ans].b=z;
p[ans].s=x*z;
p[ans++].len=y;
p[ans].a=z;
p[ans].b=y;
p[ans].s=z*y;
p[ans++].len=x;
}
sort(p+1,p+ans,comp);
memset(dp,0,sizeof(dp));
dp[1]=p[1].len; //赋初值
int flag=0;
for(i=1;i<ans;i++)
{
flag=0;
for(j=1;j<i;j++)
if((((p[i].a>p[j].a)&&(p[i].b>p[j].b))||((p[i].a>p[j].b)&&(p[i].b>p[j].a))))
{
flag=1;
if(dp[j]+p[i].len > dp[i])
dp[i]=dp[j]+p[i].len;
}
if(flag==0)//赋初值,一开始这没加,只给上面的 dp[1]=p[1].len; 赋了,就错了,调试了一下,就发现有bug了
dp[i]=p[i].len;//例如:2 10 10 1000 5 30 10000 这个用例就过不了。。
}
int max=-1;
for(i=1;i<ans;i++)
if(dp[i]>max) max=dp[i];
printf("Case %d: maximum height = %d\n",t,max);
}
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
int n,i,j,k;
int dp[100];
struct node{
int a,b,len,s;
}p[100];
bool comp(node a,node b)
{
return a.s<b.s;
}
int main()
{
int t=0;
while(scanf("%d",&n),n){
t++;
int ans=1,x,y,z;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);//一个方块 相当于 3个点
p[ans].a=x;
p[ans].b=y;
p[ans].s=x*y;
p[ans++].len=z;
p[ans].a=x;
p[ans].b=z;
p[ans].s=x*z;
p[ans++].len=y;
p[ans].a=z;
p[ans].b=y;
p[ans].s=z*y;
p[ans++].len=x;
}
sort(p+1,p+ans,comp);
memset(dp,0,sizeof(dp));
for(i=1;i<ans;i++) //这么赋初值 ,就行了,,,
dp[i]=p[i].len;
for(i=1;i<ans;i++)
for(j=1;j<i;j++)
if((((p[i].a>p[j].a)&&(p[i].b>p[j].b))||((p[i].a>p[j].b)&&(p[i].b>p[j].a))))
{
if(dp[j]+p[i].len > dp[i])
dp[i]=dp[j]+p[i].len;
}
int max=-1;
for(i=1;i<ans;i++)
if(dp[i]>max) max=dp[i];
printf("Case %d: maximum height = %d\n",t,max);
}
}