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;
}

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