1. 程式人生 > >HDU 1069 Monkey and Banana 最長上升子序列進階(動態規劃)

HDU 1069 Monkey and Banana 最長上升子序列進階(動態規劃)

HDU 1069(動態規劃)

Monkey and Banana

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Problem Description

A group of researchers are designing an experiment to test the IQ of a monkey. They will hang a banana at the roof of a building, and at the mean time, provide the monkey with some blocks. If the monkey is clever enough, it shall be able to reach the banana by placing one block on the top another to build a tower and climb up to get its favorite food.

The researchers have n types of blocks, and an unlimited supply of blocks of each type. Each type-i block was a rectangular solid with linear dimensions (xi, yi, zi). A block could be reoriented so that any two of its three dimensions determined the dimensions of the base and the other dimension was the height.

They want to make sure that the tallest tower possible by stacking blocks can reach the roof. The problem is that, in building a tower, one block could only be placed on top of another block as long as the two base dimensions of the upper block were both strictly smaller than the corresponding base dimensions of the lower block because there has to be some space for the monkey to step on. This meant, for example, that blocks oriented to have equal-sized bases couldn’t be stacked.

Your job is to write a program that determines the height of the tallest tower the monkey can build with a given set of blocks.

Input

The input file will contain one or more test cases. The first line of each test case contains an integer n, 
representing the number of different blocks in the following data set. The maximum value for n is 30. 
Each of the next n lines contains three integers representing the values xi, yi and zi. 
Input is terminated by a value of zero (0) for n.

Output

For each test case, print one line containing the case number (they are numbered sequentially starting from 1) and the height of the tallest possible tower in the format “Case case: maximum height = height”.

Sample Input


10 20 30 

6 8 10 
5 5 5 

1 1 1 
2 2 2 
3 3 3 
4 4 4 
5 5 5 
6 6 6 
7 7 7 

31 41 59 
26 53 58 
97 93 23 
84 62 64 
33 83 27 
0

Sample Output

Case 1: maximum height = 40 
Case 2: maximum height = 21 
Case 3: maximum height = 28 
Case 4: maximum height = 342

題意

一群研究人員要測一下猴子的智商,他們把香蕉放到房頂上,給猴子一些方塊,讓猴子壘方塊爬上去,處於上面的方塊長和寬都嚴格小於下面的方塊,要不然猴子怎麼落腳啊?

給出N個方塊的長、寬、高,每種方塊有無數種,求這些方塊組合起來的最大高度?

分析

首先,這些方塊的長和寬從下到上都是遞減的,只是高度不同而已;想一想最長上升子序列,每個元素的值都是依次遞增的,最後求最長的子序列長度;

如果把方塊當作數字來看的話,同樣,滿足最長上升子序列的條件,只不過每個元素的長度是方塊的高度,元素大小的比較變成了方塊長和寬的比較,然後就變成了最長上升子序列的升級版

這裡每個方塊可以使用多次,只要滿足長和寬遞減即可,所以要按長和寬排序,一個方塊有6種使用方法,長、寬、高排列組合一下就好了

狀態轉移方程:dp[i]=max(dp[i],dp[j]+a[i].z)  (j<i,a[j].x>a[i].x&&a[j].y>a[i].y)

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<cstdio>
#include<string>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#define mod 998244353
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long ll;
using namespace std;
const int maxn=200;
int dp[maxn];//表示以a[i]結尾的最長上升子序列的長度
struct Block{
    int x,y,z;
    //按長寬遞減的方式來比較方塊
    bool friend operator > (Block a,Block b){
        if(a.x>b.x&&a.y>b.y)
            return true;
        return false;
    }
}a[maxn];
//給方塊排序
bool cmp(Block a,Block b)
{
    if(a.x>b.x)
        return true;
    else if(a.x==b.x)
        return a.y>b.y;
    return false;
}
int k,n;
void turn(int x,int y,int z){
    k++;
    a[k].x=x;
    a[k].y=y;
    a[k].z=z;
}
int main(){
    int ca=1;
    while(scanf("%d",&n)!=EOF&&n){
            k=0;
        for(int i=0;i<n;i++){
            Block b;
            scanf("%d%d%d",&b.x,&b.y,&b.z);
            turn(b.x,b.y,b.z);
            turn(b.x,b.z,b.y);

            turn(b.y,b.x,b.z);
            turn(b.y,b.z,b.x);

            turn(b.z,b.x,b.y);
            turn(b.z,b.y,b.x);
        }
        sort(a+1,a+k+1,cmp);
        
        int ans=-1;
        for(int i=1;i<k;i++){//列舉子序列的終點
            dp[i]=a[i].z;//長度最短為自身
            for(int j=1;j<i;j++)//從頭向終點檢查每一個元素
                if(a[j]>a[i])//遞減
                dp[i]=max(dp[i],dp[j]+a[i].z);//狀態轉移
            ans=max(ans,dp[i]);
        }
         printf("Case %d: maximum height = %d\n",ca++,ans);
    }
}