NY-232 How to eat more Banana

最近一直都在学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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章