最近一直都在學DP,說實話,這要學的還真多,還不好理解,苦逼的人……
題目鏈接:http://acm.nyist.net/JudgeOnline/problem.php?pid=232
這題是一道完全揹包的題目,看完題目後,感覺沒有思路,就算是有也是O(n^3)的複雜度,蛋疼中……後來第二天就想到以前做到一道題……差不多,就是沒有那個高度,求最長的矩形嵌套,so……AC了。
大體思路如下:因爲有n種規格的方塊,疊起來要使得放上去的方塊的長和寬都要嚴格小於下面的方塊,而每一種都是無限使用,但顯然每一種規格的最多會用到2個,因爲疊上去的面要比下面的嚴格小,頂多能放兩個(其中有一個可以轉到其它面),再放同一種規格的就不符合要求了。所以把三維的轉化一下,定個規則,每一種規格都會形成三個不同的長,寬(x和y,x和z,y和z)的方塊,那麼就總共有3*n個方塊,給它們排個序,從面大的到面小的(規定那一面必須是各自的x,y)。轉移方程就是:
f[ i ] = max( f[ j ] ) + z[ i ]; ( 0<= j < i ; z[ i ] 是第i個方塊的高度 , max( f [ j ] ) 就是求符合第j個方塊的x,y面大於第i個方塊的x,y面的高度數)。
最後記錄最大的值就可以求解了。
代碼如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct node
{
int x,y,h;
}block[100];
int ans[110];
int cmp(const void *a,const void *b)
{
struct node *x=(struct node*)a,*y=(struct node*)b;
if( x->x != y->x ) return y->x-x->x;
else if( x->y != y->y ) return y->y - x->y;
else if( x->h != y->h ) return y->h - x->h;
else return 0;
}
int swap(int &a,int &b)
{
if( a < b ) { int temp=a; a=b,b=temp; }
}
int main()
{
int n,all=0,i,j,k=1,max;
while( scanf("%d",&n)==1 && n )
{
for( i=0; i < 3*n; i+=3 )
{
scanf("%d%d%d",&block[i].x,&block[i].y,&block[i].h); //這是某一種規格的第一種形式x,y
block[ i+1 ].x = block[ i ].x, block[ i+1 ].y = block[ i ].h, block[ i+1 ].h = block[ i ].y;//第二種形式x,h
block[ i+2 ].x = block[ i ].y, block[ i+2 ].y = block[ i ].h, block[ i+2 ].h = block[ i ].x;//第三種形式y,h
swap( block[i].x ,block[i].y ); swap( block[i+1].x,block[i+1].y ); swap( block[i+2].x,block[i+2].y ); //把x,y中大的那一個放到前面
}
qsort(block,3*n,sizeof(struct node),cmp); //按x,y面的大小來進行排序
for(i=0;i<3*n;i++) ans[i]=block[i].h;
for(i=0,all=0;i<3*n;i++)
{
for(j=0,max=0;j<i;j++)
if( block[j].x > block[i].x && block[j].y > block[i].y && max < ans[j] ) max=ans[j]; //找f(j)的最大值
if( ans[i]+max > ans[i] ) ans[i]+=max;
if( ans[i] > all ) all=ans[i];
}
printf("Case %d: maximum height = %d\n",k++,all);
}
return 0;
}