题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1069
又一个dp的题,题目大意是:给你n个木块,每个木块有长宽高三个属性,每个木块都可以使用无穷多个,
问如果将这些个木块堆起来,能达到的最大高度是多少?(每个木块的长和宽必须均大于下面的那个木块);
首先,由于每个木块可以使用无穷多次,所以,每个木块可以当成三个木块来用,三个木块的高分别为原木块的长,宽,高,所以n个木块就变成了3*n个木块,然后读入数据的时候使每个木块的长均不小于高,然后对3n个木块进行排序;长度大的在前,如果一样 宽度高的在前;
然后定义数组f[i]为最上面一个木块是i号木块时所能达到的最大高度,思路和求最长递增子序列一样;求f[i]时,令j从0
到i-1扫描a[i],(a[i]记录木块的长宽高信息),如果j号木块的长宽均大于i号木块的长宽,则i号可以放在j号的上面;
则f[i]=f[j]+a[i].h;当然最终f[i]的值取满足条件的j中高度最大的那个;
#include <iostream>
#include <cstdlib>
using namespace std;
struct tt
{
int l;
int w;
int h;
}s[10006];
int comp(const void *a,const void *b)
{
if((*(tt *)a).l>(*(tt *)b).l)
return -1;
if((*(tt *)a).l<(*(tt *)b).l)
return 1;
if((*(tt *)a).w>(*(tt *)b).w)
return -1;
if((*(tt *)a).w<(*(tt *)b).w)
return 1;
}
int len;
void execute(int fl)
{
int i,j;
__int64 f[10006];
for(i=0;i<len;i++)
f[i]=s[i].h;
for(i=0;i<len;i++)
{
for(j=0;j<i;j++)
{
if(s[i].w<s[j].w&&s[i].l<s[j].l)
{
if(f[i]<s[i].h+f[j])
f[i]=s[i].h+f[j];
}
}
}
__int64 ans;
ans=f[0];
for(i=0;i<len;i++)
if(ans<f[i])
ans=f[i];
printf("Case %d: maximum height = %I64d\n",fl+1,ans);
}
int main()
{
int n;
int a,b,c;
int i;
int t;
int fl=0;
while(cin>>n&&n)
{
len=0;
for(i=0;i<n;i++)
{
cin>>a>>b>>c;
s[len].l=a;
s[len].w=b;
s[len].h=c;
len++;
s[len].l=a;
s[len].w=c;
s[len].h=b;
len++;
s[len].l=c;
s[len].w=b;
s[len].h=a;
len++;
}
for(i=0;i<len;i++)
{
if(s[i].l<s[i].w)
{
t=s[i].l;
s[i].l=s[i].w;
s[i].w=t;
}
}
qsort(s,len,sizeof(s[0]),comp);
execute(fl++);
}
return 0;
}