HDU-1069 Monkey and Banana(典型DP)

题目描述

一组研究人员正在设计一项实验,以测试猴子的智商。他们将挂香蕉在建筑物的屋顶,同时,提供一些砖块给这些猴子。如果猴子足够聪明,它应当能够通过合理的放置一些砖块建立一个塔,并爬上去吃他们最喜欢的香蕉。

研究人员有n种类型的砖块,每种类型的砖块都有无限个。第i块砖块的长宽高分别用xi,yi,zi来表示。 同时,由于砖块是可以旋转的,每个砖块的3条边可以组成6种不同的长宽高。

在构建塔时,当且仅当A砖块的长和宽都分别小于B砖块的长和宽时,A砖块才能放到B砖块的上面,因为必须留有一些空间让猴子来踩。

你的任务是编写一个程序,计算猴子们最高可以堆出的砖块们的高度。

输入格式

输入文件包含多组测试数据。
每个测试用例的第一行包含一个整数n,代表不同种类的砖块数目。n<=30.
接下来n行,每行3个数,分别表示砖块的长宽高。
当n= 0的时候,无需输出任何答案,测试结束。

输出格式

对于每组测试数据,输出最大高度。格式:Case 第几组数据: maximum height = 最大高度

样例输入

1
10 20 30 
2 
6 8 10 
5 5 5 
7 
1 1 1 
2 2 2 
3 3 3 
4 4 4 
5 5 5 
6 6 6 
7 7 7 
5 
31 41 59 
26 53 58 
97 93 23 
84 62 64 
33 83 27 
0

样例输出

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






题解:

  • 对于每一块砖,有三条边可以作为高,则另外两条边可分别做长、宽,故共有6种摆法
  • 将6*n种砖加入到数组中,再将其按长度递增排序(长度相等则宽度递增)
  • 定义状态dp[i]将第i个箱子作为最底部时的最高高度,因已保证长度递增,所以只需要判断宽度和长度是否严格递增。如此一来,问题便变得像最长递增子串了。
  • 状态转移: dp[i]=max(dp[k]+a[i].height)k<ia[i].length>a[k].length,  a[i].width>a[k].widthdp[i] = \max (dp[k]+a[i].height) 其中k<i且a[i].length > a[k].length,\ \ a[i].width > a[k].width
#include <bits/stdc++.h>
using namespace std;

const int maxn = 35 * 6;

struct box{
    int l,w,s,h;
};

bool cmp(box &a, box &b)
{
    if(a.l==b.l) return a.w < b.w;
    return a.l < b.l;
}

box bo[maxn];
int dp[maxn];

int solve(int sn)
{
    int ans = 0;
    for(int i=0;i<sn;i++)
    {
        dp[i] = bo[i].h;
        for(int j=0;j<i;j++)
            if(bo[j].l<bo[i].l && bo[j].w < bo[i].w && dp[j]+bo[i].h > dp[i])
                dp[i] = dp[j]+bo[i].h;
        ans = max(ans, dp[i]);
    }
    return ans;
}

int main()
{
    int n,kase = 0;
    cin >> n;
    while(n)
    {
        int a,b,c;
        for(int i=0;i<n;i++)
        {
            scanf("%d %d %d",&a,&b,&c);
            // 六种摆法
            bo[i*6+5].h = bo[i*6+4].w = bo[i*6+3].l = bo[i*6+2].h = bo[i*6+1].w = bo[i*6].l = a;
            bo[i*6+5].l = bo[i*6+4].h = bo[i*6+3].w = bo[i*6+2].w = bo[i*6+1].l = bo[i*6].h = b;
            bo[i*6+5].w = bo[i*6+4].l = bo[i*6+3].h = bo[i*6+2].l = bo[i*6+1].h = bo[i*6].w = c;
        }
        int sn = 6*n;
        sort(bo, bo+sn, cmp);
        cout <<"Case " << ++kase << ": maximum height = " << solve(sn) << endl;
        scanf("%d",&n);
    }


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