列表

详情


1105. 填充书架

给定一个数组 books ,其中 books[i] = [thicknessi, heighti] 表示第 i 本书的厚度和高度。你也会得到一个整数 shelfWidth

按顺序 将这些书摆放到总宽度为 shelfWidth 的书架上。

先选几本书放在书架上(它们的厚度之和小于等于书架的宽度 shelfWidth ),然后再建一层书架。重复这个过程,直到把所有的书都放在书架上。

需要注意的是,在上述过程的每个步骤中,摆放书的顺序与你整理好的顺序相同

每一层所摆放的书的最大高度就是这一层书架的层高,书架整体的高度为各层高之和。

以这种方式布置书架,返回书架整体可能的最小高度。

 

示例 1:

输入:books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelf_width = 4
输出:6
解释:
3 层书架的高度和为 1 + 3 + 2 = 6 。
第 2 本书不必放在第一层书架上。

示例 2:

输入: books = [[1,3],[2,4],[3,2]], shelfWidth = 6
输出: 4

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int minHeightShelves(vector<vector<int>>& books, int shelfWidth) { } };

python3 解法, 执行用时: 32 ms, 内存消耗: 15.1 MB, 提交时间: 2022-12-08 10:27:02

'''
用 dp[i] 表示放置前 i 本书所需要的书架最小高度,初始值 dp[0] = 0,其他为最大值 1000*1000。
遍历每一本书,把当前这本书作为书架最后一层的最后一本书,将这本书之前的书向后调整,
看看是否可以减少之前的书架高度。状态转移方程为 dp[i] = min(dp[i] , dp[j - 1] + h),
其中 j 表示最后一层所能容下书籍的索引,h 表示最后一层最大高度。
'''
class Solution:
    def minHeightShelves(self, books: List[List[int]], shelf_width: int) -> int:
        n = len(books)
        dp = [1000000] * (n + 1)
        dp[0] = 0
        for i in range(1, n + 1):
            tmp_width, j, h = 0, i, 0
            while j > 0:
                tmp_width += books[j - 1][0]
                if tmp_width > shelf_width:
                    break
                h = max(h, books[j - 1][1])
                dp[i] = min(dp[i], dp[j - 1] + h)
                j -= 1
        return dp[-1]

java 解法, 执行用时: 0 ms, 内存消耗: 40.9 MB, 提交时间: 2022-12-08 10:25:55

class Solution {
    public int minHeightShelves(int[][] books, int shelf_width) {
        int n = books.length;
        int[] dp = new int[n + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[n] = 0;
        // 倒着处理书本,因为数组的最后一个在整个书架的最上面
        for (int i = n - 1; i >= 0; --i) {
            // 首先假设这一层高度为 0
            int maxHeight = 0;
            // 当前层剩余的宽度为 leftWidth
            int leftWidth = shelf_width;
            // 根据处理到的书以及之前出现的,尝试把之前出现的书放到当前层,看看能不能达到最小值
            for (int j = i; j < n && leftWidth >= books[j][0]; ++j) {
                maxHeight = Math.max(maxHeight, books[j][1]);
                dp[i] = Math.min(dp[i], maxHeight + dp[j + 1]);
                leftWidth -= books[j][0];
            }
        }
        return dp[0];
    }
}

cpp 解法, 执行用时: 4 ms, 内存消耗: 7.8 MB, 提交时间: 2022-12-08 10:25:34

class Solution {
public:
    int minHeightShelves(vector<vector<int>>& books, int shelf_width) {
        vector<int> dp(books.size() + 1, INT_MAX);
        dp[books.size()] = 0;
        for (int i = books.size() - 1; i >= 0; --i) {
            int max_book_height = 0;
            int left_width = shelf_width;
            // 把第 j 本书拿到第 i 本书后面
            for (int j = i; j < books.size() && left_width >= books[j][0]; ++j) {
                max_book_height = max(max_book_height, books[j][1]);
                dp[i] = min(dp[i], max_book_height + dp[j+1]);
                left_width -= books[j][0];
            }
        }
        return dp[0];
    }
};

python3 解法, 执行用时: 48 ms, 内存消耗: 15.2 MB, 提交时间: 2022-12-08 10:24:11

'''
将第i本书当做最后一本书,我们需要求i本书的最小高度f[i]。
所以如果最后一本书放到新的一层中,f[i] = f[i-1] + books[i-1][1]
最后一本书也可以和他前一本书一同放到新的一层。这时:f[i] = f[i-2] + max(books[i-1][1],books[i-2][1])
'''
class Solution:
    def minHeightShelves(self, books: List[List[int]], shelf_width: int) -> int:
        import sys
        n = len(books)
        f = [sys.maxsize]*(n+1)
        f[0] = 0
        for i in range(1,n+1):
            cur_height = 0 #以第i本书作为最后一本书,最后一层的高度
            cur_weight = 0 #以第i本书作为最后一本书,最后一层的宽度
            for j in range(i,0,-1):
                cur_height = max(cur_height,books[j-1][1])
                cur_weight += books[j-1][0]
                if(cur_weight>shelf_width):
                    break
                f[i] = min(f[i],f[j-1] + cur_height)
        return f[-1]

上一题