Monkey and Banana(HDU-1069)


1 题意

  给定 n n n种木块,每种木块由(长,宽,高)标识,并且有无限多个。现要求层叠木块(可以选择任意一面作为底面),上面木块的底面的长和宽要严格小于下面木块。问:最多可以层叠多高。
  链接:link

2 思路

2.1 动态规划

  由于木块是无限的,所以可以考虑木块的所有的摆放状态(每个木块有3种摆放状态)。按底面积对木块从小到大排序,这样状态转移的时候就只需要在前面寻找一个合适的木块(因为底面积大的木块是肯定不能放在上面的)。
  状态 d p [ i ] dp[i] dp[i]表示把第 i i i个木块放在底部最多能层叠多高。
  转移 d p [ j ] = max ⁡ i < j ∧ x i < x j ∧ y i < y j ( d p [ i ] ) + z j dp[j]= \max_{i<j \wedge x_{i}<x_{j} \wedge y_{i}<y_{j}}(dp[i])+z_{j} dp[j]=maxi<jxi<xjyi<yj(dp[i])+zj

2.1.1 时间复杂的分析

  由状态转移过程可知,时间复杂度为 O ( n 2 ) \mathcal{O}(n^{2}) O(n2)

2.1.2 实现

#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e2+10;
struct Rec{
    int x,y,z;
    Rec(int a,int b,int c):x(a),y(b),z(c){}
};
int n,k=0,dp[N];
vector<Rec> vec;
bool operator<(Rec& a,Rec& b){
    return a.x*a.y<b.x*b.y;
}
bool cmp(Rec& a,Rec& b){
    return a.x>b.x&&a.y>b.y||a.x>b.y&&a.y>b.x;
}
int main(){
    while(~scanf("%d",&n)&&n){
        vec.clear();
        for(int i=0;i<n;i++){
            int x,y,z;scanf("%d %d %d",&x,&y,&z);
            vec.push_back(Rec(x,y,z));
            vec.push_back(Rec(z,y,x));
            vec.push_back(Rec(x,z,y));
        }
        sort(vec.begin(),vec.end());
        memset(dp,0,sizeof(dp));
        int mx=0;
        for(int i=0;i<vec.size();i++){
            dp[i]=vec[i].z;
            for(int j=0;j<i;j++){
                if(cmp(vec[i],vec[j])){
                    dp[i]=max(dp[i],dp[j]+vec[i].z);
                    mx=max(dp[i],mx);
                }
            }
        }
        printf("Case %d: maximum height = %d\n",++k,mx);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值