hdu 4001 dp To Miss Our Children Time

题意:

小孩子玩积木堆房子的情景:
每组测试数据第一行给出n,代表接下来有n块砖;
接下来n行,每行给出砖的长,宽,高,属性(a,b,c,d);
属性d:d=0:该砖的长度和宽度(a,b)要比垫在他下面的砖的长,宽大或者相等;就是长>=长,宽>=宽
d=1:改砖的宽度和长度要比下面的砖的长度大或者相等,同时,该砖的宽度值和面积值要比下面的砖的面积值大;即长>=长,宽>=宽,面积>面积。也就是长>=长&&宽>=宽&&(长>长||宽>宽)
d=2:该砖的长度和宽度(a,b)要比垫在他下面的砖的长,宽大(严格大于);长>长,宽>宽。
要求输出该给出的所有的砖块所能听堆砌的最大高度。

排序的原因是让数组后面的砖头一定可以叠在前面的砖头上。

dp[i]表示以i为最上面那一块砖头所能迭的最大高度。

                                                    状态转移方程: dp[i] = max(dp[i],dp[j] + b[i].z);

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
struct block{
    __int64 x,y,z;      int d;
    bool operator < (const block & cmp) const{
        if(x != cmp.x) return x < cmp.x;
        if(y != cmp.y) return y < cmp.y;
        return d > cmp.d;
    }
}b[1010];
int n;
__int64 dp[1010];
int main()
{
    while(~scanf("%d",&n) && n){
        for(int i = 1; i <= n; i ++){
            scanf("%I64d%I64d%I64d%d",&b[i].x,&b[i].y,& b[i].z,& b[i].d);
        //为什么要交换呢?
            if(b[i].x < b[i].y) swap(b[i].x,b[i].y);
        }
        sort(b + 1, b + 1 + n);
        __int64 ans = b[1].z;//
        for(int i = 1; i <= n; i ++){
            dp[i] = b[i].z;
            ans = max(dp[i],ans);
        }
    //dp[i]表示最后一个是i的最大高度
        for(int i = 2; i <= n; i ++){
            if(b[i].d == 0){
                for(int j = 1; j < i; j ++){
                    if(b[i].x >= b[j].x && b[i].y >= b[j].y)
                        dp[i] = max(dp[i],dp[j] + b[i].z);
                }
            }else if(b[i].d == 1){
                for(int j = 1; j < i; j ++){
                    if(b[i].x >= b[j].x && b[i].y >= b[j].y &&(b[i].y>b[j].y||b[i].x>b[j].x) )
                        dp[i] = max(dp[i],dp[j] + b[i].z);
                }
            }else{
                for(int j = 1; j < i; j ++){
                    if(b[i].x > b[j].x && b[i].y > b[j].y)
                        dp[i] = max(dp[i],dp[j] + b[i].z);
                }
            }
            if(ans < dp[i])
                ans = dp[i];
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值