Leetcode 1691. 堆疊長方體的最大高度

https://leetcode.cn/problems/maximum-height-by-stacking-cuboids/description/

給你 n 個長方體 cuboids ,其中第 i 個長方體的長寬高表示爲 cuboids[i] = [widthi, lengthi, heighti](下標從 0 開始)。
請你從 cuboids 選出一個 子集 ,並將它們堆疊起來。
如果 widthi <= widthj 且 lengthi <= lengthj 且 heighti <= heightj ,你就可以將長方體 i 堆疊在長方體 j 上。
你可以通過旋轉把長方體的長寬高重新排列,以將它放在另一個長方體上。
返回 堆疊長方體 cuboids 可以得到的 最大高度 。
示例 1:

輸入:cuboids = [[50,45,20],[95,37,53],[45,23,12]]
輸出:190
解釋:
第 1 個長方體放在底部,53x37 的一面朝下,高度爲 95 。
第 0 個長方體放在中間,45x20 的一面朝下,高度爲 50 。
第 2 個長方體放在上面,23x12 的一面朝下,高度爲 45 。
總高度是 95 + 50 + 45 = 190 。

示例 2:
輸入:cuboids = [[38,25,45],[76,35,3]]
輸出:76
解釋:
無法將任何長方體放在另一個上面。
選擇第 1 個長方體然後旋轉它,使 35x3 的一面朝下,其高度爲 76 。


示例 3:
輸入:cuboids = [[7,11,17],[7,17,11],[11,7,17],[11,17,7],[17,7,11],[17,11,7]]
輸出:102
解釋:
重新排列長方體後,可以看到所有長方體的尺寸都相同。
你可以把 11x7 的一面朝下,這樣它們的高度就是 17 。
堆疊長方體的最大高度爲 6 * 17 = 102 。
 
提示:
n == cuboids.length
1 <= n <= 100
1 <= widthi, lengthi, heighti <= 100

根據題目的數據範圍
我們將每個長方體的可能的長寬高組合都考慮進去,那麼每個長方體有6個組合(123,132,213,231,312,321),製作一個新的數據隊列進行01揹包動態規劃,
保證不多次選擇同一個長方體也是能夠通過的。複雜度是O(n^2),只是n擴大了6倍。
我們這裏考慮優化計算方式.
1 將每個長方體的三個維度進行從小到大排序
2 按照排序後的長方體按照三個維度關鍵字進行排序。
3 進行dp,尋找符合條件的最長上升子序列(排序中,長方體最大的那個維度作爲高來使用)
這種做法需要證明兩個問題:

1 爲什麼每個長方體的三個維度進行排序,再按照三個維度關鍵字進行排序,就保證正確答案在裏面。

也就是長方體{1,2,3}能堆疊在長方體{4,5,6}, {2,3,1}能堆疊在{6,4,5}上 是相同。
{4,5,3}能堆疊在(5,3,7}上和 {3,4,5}能堆疊在{3,5,7}上是相同的。

設兩個長方體,A={a1,a2,a3},B={b1,b2,b3} ,並且a1<=a2<=a3, b1<=b2<=b3

A能堆疊在B上,要求證明當且僅當a1<=b1 ,a2<=b2,a3<=b3

1 a1<=b1 ,a2<=b2,a3<=b3    推導出===>  A能堆疊在B上 這是題目的定義
2  A能堆疊在B上  推導出==>   a1<=b1,a2<=b2,a3<=b3

因爲已有a1<=a2<=a3, b1<=b2<=b3,A能堆疊在B上,那麼一定有 最小的a1<=b1,最大的 b3>=(a1,a2,a3) 也就是a3<=b3,否則A不可能堆疊在B上
同樣的a2不可能>B3,如果a2>B2,那麼A不可能堆疊在B上。所以a2<=b2.

2 爲什麼長方體排序後,使用最大的維度作爲高度,就得到 堆疊長方體的最大高度。

這是因爲我們在求最長遞增子序列,在確定了子序列的最長長度,使用維度最高的邊作爲高度,那麼他們的高度和就是最大高度。
假設有其他更高的不全部使用最長維度作爲高度的選擇組合,這個選擇組合的長度需要比最長上升序列的長度至少要大一。
但是不存在比最長上升序列更長的上升序列。 所以把最長的邊作爲高是最優的。

兩個問題解決後,代碼如下

class Solution {
public:
    int maxHeight(vector<vector<int>>& cuboids) {
        //長方體的維度排序和長方體的三維度排序
        for (auto& e : cuboids) {
            sort(e.begin(), e.end());
        }
        sort(cuboids.begin(),cuboids.end());
         //插入一個元素,dp可以從1 開始 避免邊界問題
        cuboids.insert(cuboids.begin(), vector<int>{0,0,0});
        int dp[105]; memset(dp,-0x3f,sizeof dp);
        dp[0] = 0;
        //dp[i] 等於以第i個長方體結尾的最大高度
        for (int i = 1; i < cuboids.size(); i++) {
            for (int j = 0; j < i;j++) {
                if (cuboids[i][0] >= cuboids[j][0] && cuboids[i][1] >= cuboids[j][1] && cuboids[i][2] >= cuboids[j][2]) {
                    dp[i] = max(dp[i], dp[j] + cuboids[i][2]);
                }
            }
        }
        //得到以任意長方體結尾的最大高度中的最大值
        int ans = 0;
        for (int i = 0; i < cuboids.size(); i++) {
            ans = max(ans, dp[i]);
        }

        return ans;
    }
};

我的視頻題解空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章