HDU 1069 Monkey and Banana 入门dp + 离散化

本文探讨了一个经典的砖块堆叠问题,通过动态规划(DP)的方法求解砖块堆叠的最大高度。文章详细介绍了如何进行离散化处理,以及如何使用DP状态转移方程来解决这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

又读错题了...砖块每类有无数个...不是只能用一次

题意:

有m种砖,每种砖有长宽高3种属性,把砖摞成一摞,问最高能多高.

砖i能放在砖j上 当且仅当 i长<j长&&i宽<j宽.

思路:

一开始想直接dp,但是发现没有给value的大小,索性离散化一下.

dp[i][j]表示当前摞的顶端宽为v[i],长为v[j],dp[i][j]为当前最优高度

用每个状态的砖块更新dp[i][j]即可

离散化:

VALUE:                          离散化前的值   

value:                             离散化后的值

知道value找VALUE:       v[value]  → VALUE

知道VALUE找value:       lower_bound(v,VALUE)-v.begin()  →  value

代码:

#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;

const int M=2e5+5;
const int inf=1e9+5;

int n,dp[100][100];
int x[35],y[35],z[35];
int main() {
    int caz=1;
    while(~scanf("%d",&n)&&n) {
        vector<int>v;
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; i++) {
            scanf("%d%d%d",&x[i],&y[i],&z[i]);
            v.push_back(x[i]);
            v.push_back(y[i]);
            v.push_back(z[i]);

        }
        sort(v.begin(),v.end());
        int m=unique(v.begin(),v.end())-v.begin();
        v.erase(v.begin()+m,v.end());
//      erase后, m就是v.size() 
        for(int i=1; i<=n; i++) {
            int posx=lower_bound(v.begin(),v.end(),x[i])-v.begin();
            int posy=lower_bound(v.begin(),v.end(),y[i])-v.begin();
            int posz=lower_bound(v.begin(),v.end(),z[i])-v.begin();
            dp[posx][posy]=max(dp[posx][posy],z[i]);
            dp[posy][posx]=max(dp[posy][posx],z[i]);

            dp[posz][posy]=max(dp[posz][posy],x[i]);
            dp[posy][posz]=max(dp[posy][posz],x[i]);

            dp[posx][posz]=max(dp[posx][posz],y[i]);
            dp[posz][posx]=max(dp[posz][posx],y[i]);
        }
        for(int i=m-1; i>=0; i--) {
            for(int j=m-1; j>=0; j--) {
                for(int k=1; k<=n; k++) {
                    int posx=lower_bound(v.begin(),v.end(),x[k])-v.begin();
                    int posy=lower_bound(v.begin(),v.end(),y[k])-v.begin();
                    int posz=lower_bound(v.begin(),v.end(),z[k])-v.begin();
                    if(i>posx&&j>posy)
                        dp[posx][posy]=max(dp[posx][posy],dp[i][j]+z[k]);
                    if(i>posy&&j>posx)
                        dp[posy][posx]=max(dp[posy][posx],dp[i][j]+z[k]);

                    if(i>posz&&j>posy)
                        dp[posz][posy]=max(dp[posz][posy],dp[i][j]+x[k]);
                    if(i>posy&&j>posz)
                        dp[posy][posz]=max(dp[posy][posz],dp[i][j]+x[k]);

                    if(i>posx&&j>posz)
                        dp[posx][posz]=max(dp[posx][posz],dp[i][j]+y[k]);
                    if(i>posz&&j>posx)
                        dp[posz][posx]=max(dp[posz][posx],dp[i][j]+y[k]);
                }
            }
        }
        int ans=0;
        for(int i=0; i<m; i++) {
            for(int j=0; j<m; j++) {
                ans=max(ans,dp[i][j]);
            }
        }
        printf("Case %d: maximum height = %d\n",caz++,ans);
    }
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值