HDU1069 猴子叠木块

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1069

研究人员有n种类型的块,并且每种类型的块都是无限制的。 每个i型块是具有线性尺寸(xi,yi,zi)的矩形固体。 块可以重新定向,使得它的三个维度中的任何两个确定基座的尺寸,而另一个尺寸是高度。

他们想要确保通过堆放块可能的最高的塔可以到达屋顶。 问题在于,在建造塔架时,只能将一块块放置在另一块的顶部,只要上块的两个基座尺寸都严格小于下块的相应底座尺寸,因为必须 一些空间让猴子踩上。 这意味着,例如,面向具有相等尺寸的基座的块不能被堆叠。

你的工作就是编写一个程序,用来确定猴子能用一组给定的块建立的最高塔的高度。

Sample Input
  
  
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
 

Sample Output
  
  
Case 1: maximum height = 40 Case 2: maximum height = 21 Case 3: maximum height = 28 Case 4: maximum height = 342
思路:这道题给出一些木块的尺寸,每种木块无限个,求出能堆最大高度。

首先,每个木块可以有3!6种摆法,每种摆法构成1种模型。每种模型最多用一次,因为长宽要越来越小。

而且要先用大的。所以可以以长a从大到小排序。dp[i]表示前i种模型能堆的最大高度,并且第i种在最上面。

dp[i]=max(dp[j]+a[i]),j<i。 从前i种找到最优解再堆上第i个。然后找到以第i个模型为顶点的最高堆。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std;
struct tans
{
    int a, b, h;
};
tans block[300];
int dp[300];
int len;//保存模型数量
void input(int a,int b,int h)
{
    len++;
    block[len].a = a;
    block[len].b = b;
    block[len].h = h;
    
}
bool cmp(tans m, tans n)//按照长度从大到小
{
    if (m.a > n.a)
        return 1;
    else return 0;
}
int main()
{

    int n,s=0,i,aa,bb,hh,j;
    while (~scanf("%d", &n) && n != 0)
    {
        s++; len = 0;
        for (i = 0; i < n; i++)
        {
            scanf("%d%d%d", &aa, &bb, &hh);
            input(aa, bb, hh); input(aa, hh, bb);
            input(bb, aa, hh); input(bb, hh, aa);
            input(hh, aa, bb); input(hh, bb, aa);
        }
        sort(block + 1, block + 1 + len, cmp);
        dp[1] = block[1].h;
        for (i = 2; i <= len; i++)
        {
            dp[i] = block[i].h;//至少为第i个本身的高度
            for (j = i-1; j >= 1; j--)
            {
                if(block[i].a<block[j].a&&block[i].b<block[j].b)//长宽必须满足
                dp[i] = max(dp[i], dp[j] + block[i].h);//找到前J块中的最大值
            }
        }
        int mmax = 0;
        for (j = 1; j <= len; j++)
            mmax = max(mmax, dp[j]);
        printf("Case %d: maximum height = %d\n",s, mmax);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值