[恢]hdu 1069

2011-12-22 17:22:12

地址:http://acm.hdu.edu.cn/showproblem.php?pid=1069

题意:有n种立方体,长宽高分别是x[i], y[i], z[i],每种数量无限。可以随意旋转。把他们垒起来,要求上面的立方体底面长和宽一定要分别小于下面立方体顶面的长和宽。问最高能垒多高。

mark:一开始没看到数量无限,以为是单个的。想了好久不会做,后来看别人的解释才知道。

每个方块扩展成3个,分别穷举出3边各为高的情况,排序,然后dp。本质是LIS。还蛮简单的。

但是wa了n次,快折腾死我了。排序的策略我选择的是先x和x比,然后y和y比。但是我忽略了有x1<y2 && x2<y1的情况。。。

可以换成按面积排序,也可以换成按min(x,y)排序。总之要保证小的在前大的在后。

代码:

# include <stdio.h>
# include <stdlib.h>


typedef struct node{
int x, y, z ;
}node ;


int n ;
node pt[1010*3] ;
int dp[1010*3] ;


int max(int a, int b){return a>b?a:b;}


int cmp(const void *a, const void *b)
{
node *p = (node*)a, *q = (node*)b ;
// if (p->x != q->x) return p->x - q->x ;
// return p->y - q->y ;
return p->x*p->y - q->x * q->y ;
}


int gao()
{
int i, j, ans ;
qsort(pt, 3*n, sizeof(node), cmp) ;
ans = pt[0].z ;
for (i = 0 ; i < 3*n ; i++)
{
dp[i] = pt[i].z ;
for (j = 0 ; j < i ; j++)
{
if ((pt[j].x < pt[i].x && pt[j].y < pt[i].y) ||
(pt[j].y < pt[i].x && pt[j].x < pt[i].y))
dp[i] = max(dp[i], dp[j]+pt[i].z) ;
}
ans = max(ans, dp[i]) ;
}
return ans ;
}


int main ()
{
int a, b, c, i, nCase = 1 ;
while (~scanf ("%d", &n) && n)
{
for (i = 0 ; i < n ; i++)
{
scanf ("%d%d%d", &a, &b, &c) ;
pt[3*i].x = a, pt[3*i].y = b, pt[3*i].z = c ;
pt[3*i+1].x = b, pt[3*i+1].y = c, pt[3*i+1].z = a ;
pt[3*i+2].x = c, pt[3*i+2].y = a, pt[3*i+2].z = b ;
}
printf ("Case %d: maximum height = %d\n",nCase++, gao()) ;
}
return 0 ;
}



posted @ 2012-01-06 23:26  Seraph2012  阅读(200)  评论(0编辑  收藏  举报