【贪心 + 最长上升子序列】

LeetCode 12.10 每日一题 堆叠正方体的最大高度

算法:贪心 + DP

  1. 首先要注意到题目条件说的,如果一个长方体(长宽高为 a 1 ,   b 1 ,   c 1 a_1, \space b_1, \space c_1 a1, b1, c1)可以放在另一个长方体(长宽高为 a 2 ,   b 2 ,   c 2 a_2, \space b_2, \space c_2 a2, b2, c2)上方,那就意味着 a 1 ⩽ a 2 ,   b 1 ⩽ b 2 ,   c 1 ⩽ c 2 (1) a_1 \leqslant a_2, \space b_1 \leqslant b_2, \space c_1 \leqslant c_2 \tag 1 a1a2, b1b2, c1c2(1) 那么我们可以有一个合理猜测 —— 将各个长方体最长的边作为垒起来的高,这样就会得到最优结果。

  2. 我们先来证明一个性质,就是两个长方体,已经满足了式子 ( 1 ) (1) (1),现将两个长方体的长宽高重新按升序排序,仍然满足式子 ( 1 ) (1) (1)。设当前已经将 a 1 ,   b 1 ,   c 1 a_1, \space b_1, \space c_1 a1, b1, c1 排好序,即 a 1 ⩽ b 1 ⩽ c 1 (2) a_1 \leqslant b_1 \leqslant c_1 \tag 2 a1b1c1(2) 若此时 a 2 ,   b 2 ,   c 2 a_2, \space b_2, \space c_2 a2, b2, c2 已经是升序,那肯定成立。若其中 b 2 ⩾ c 2 b_2 \geqslant c_2 b2c2,则调换其顺序,对应关系如下: a 1    b 1    c 1 a_1 \space \space b_1 \space \space c_1 a1  b1  c1 a 2    c 2    b 2 a_2 \space \space c_2 \space \space b_2 a2  c2  b2 现由 c 2 ⩾ c 1 ⩾ b 1 ,   b 2 ⩾ c 2 ⩾ c 1   及   式 子   ( 2 ) c_2 \geqslant c_1 \geqslant b_1, \space b_2 \geqslant c_2 \geqslant c_1 \space 及 \space 式子 \space (2) c2c1b1, b2c2c1   (2) 得式子 ( 1 ) (1) (1) 仍成立,若 a 2 ⩾ b 2 a_2 \geqslant b_2 a2b2,则继续如法炮制。所以该性质成立。

  3. 接着是贪心的证明。设贪心解答案为 r e s res res,最优解答案为 a n s ans ans,那么首先一定有 r e s ⩽ a n s res \leqslant ans resans。接下来证明 r e s ⩾ a n s res \geqslant ans resans。不妨设最优解里存在一个不是以某个长方体的最长边为高的,那么就一定是以更短的或是一样长的另一条边作为高,由于最优解也是一个,所以一定满足 a 1 ⩽ a 2 ,   b 1 ⩽ b 2 ,   c 1 ⩽ c 2 a_1 \leqslant a_2, \space b_1 \leqslant b_2, \space c_1 \leqslant c_2 a1a2, b1b2, c1c2 的要求,此时将这个与贪心解不一样的地方转化为贪心解,由上述 2. 2. 2. 的证明,此时仍然满足式子 ( 1 ) (1) (1) 的要求,而得到的结果一定不会变差,所以有 r e s ⩾ a n s res \geqslant ans resans,综上有 a n s = r e s ans = res ans=res,也就是 贪心解即是最优解

  4. 所以我们可以将每个长方体的长宽高重新按升序排序;而对外层,也就是所有长方体,我们可以升序排,也可以逆序排。如果是升序,那相当于求一个最长上升子序列,也就是先从最顶层开始堆方块;如果是降序,那相当于求一个最长下降子序列,也就是先从最底层开始堆方块。这里采用升序

  5. f ( i ) f(i) f(i) 表示以第 i i i 个长方体作为底的最大堆叠高度,则就有 f ( i ) = m a x ( f ( i ) , f ( j ) + h e i g h t [ i ] ) f(i) = max(f(i), f(j) + height[i]) f(i)=max(f(i),f(j)+height[i]) 0 ⩽ j < i 0 \leqslant j \lt i 0j<i,即从前 i − 1 i - 1 i1 个长方体中选择一个长方体能够满足条件,接在 i i i 上,由于当前的 h e i g h t [ i ] height[i] height[i] 是定值,所以只需要 f ( j ) f(j) f(j) 最大。

C ++ 代码
#define all(x) x.begin(), x.end()

class Solution {
public:
    int maxHeight(vector<vector<int>>& c) {
        int n = c.size();
        for (auto &x: c) sort(all(x));
        sort(all(c));
        vector<int> f(n);
        int res = 0;
        for (int i = 0; i < n; i ++ ) {
            f[i] = c[i][2];
            for (int j = 0; j < i; j ++ )
                if (c[j][1] <= c[i][1] && c[j][2] <= c[i][2])
                    f[i] = max(f[i], f[j] + c[i][2]);
            res = max(res, f[i]);
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值