【每日一题Day186】LC1105填充书架 | dp

填充书架【LC1105】

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

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

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

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

  • 例如,如果这里有 5 本书,那么可能的一种摆放情况是:第一和第二本书放在第一层书架上,第三本书放在第二层书架上,第四和第五本书放在最后一层书架上。

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

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

小忙 写简略点

dfs+记忆化:选或不选
  • 思路:

    感觉递推的形式不是很好写,所以一开始的想法是dfs+记忆化。每遇到一本书,我们可以选择新建一层放置这本书,也可以选择在上一次继续放置这本书,影响结果的有两个因素:该层已经摆放的书的宽度以及最大高度。因此在dfs过程需要记录这两个值,定义 d f s ( i , w i d t h , m a x H e i g h t ) dfs(i,width,maxHeight) dfs(i,width,maxHeight)为上一层已经摆放的书的宽度为 w i d t h width width,并且最大高度为 m a x H e i g h t maxHeight maxHeight时,摆放第 i i i本书及剩下的书全部摆放完毕需要的最小高度。那么 d f s ( 0 , 0 , 0 ) dfs(0,0,0) dfs(0,0,0)即为最终答案

  • 实现:选或不选

    class Solution {
        int[][] dp;
        int[][] books;
        int shelfWidth;
        public int minHeightShelves(int[][] books, int shelfWidth) {
            int n = books.length;
            dp = new int[n + 1][shelfWidth + 1];
            this.books = books;
            this.shelfWidth = shelfWidth;
            return dfs(0, 0, 0);
        }
        public int dfs(int i, int width, int maxHeight){
            if (i == books.length) return maxHeight;
            if (dp[i][width] != 0) return dp[i][width];
            // 新建一层
            int res = maxHeight + dfs(i + 1, books[i][0], books[i][1]);
            // 如果宽度满足要求 那么可以继续往后面放
            if (width + books[i][0] <= shelfWidth){
                 res = Math.min(res, dfs(i + 1, width +books[i][0], Math.max(maxHeight, books[i][1])));
            }
            dp[i][width] = res;
            return res;
    
        }
    }
    
    • 复杂度

      • 时间复杂度: O ( 2 n ) O(2^n) O(2n)
      • 空间复杂度: O ( n ∗ s h e l f W i d t h ) O(n*shelfWidth) O(nshelfWidth)
dfs+记忆化:枚举选到哪个
  • 实现:

    定义 d f s ( i ) dfs(i) dfs(i)为摆放第 i i i本书及剩下的书全部摆放完毕需要的最小高度。那么 d f s ( 0 ) dfs(0) dfs(0)即为最终答案

    class Solution {
        int[] dp;
        int[][] books;
        int shelfWidth;
        public int minHeightShelves(int[][] books, int shelfWidth) {
            int n = books.length;
            dp = new int[n + 1];
            this.books = books;
            this.shelfWidth = shelfWidth;
            return dfs(0);
        }
        public int dfs(int i){
            if (i == books.length) return 0;
            if (dp[i] != 0) return dp[i];
            int width = 0, maxHeight = 0, res = Integer.MAX_VALUE;
            for (int j = i; j < books.length; j++){
                width += books[j][0];
                if (width > shelfWidth) break;// 无法放书
                maxHeight = Math.max(maxHeight, books[j][1]);
                res = Math.min(res, dfs(j + 1) + maxHeight);
            }     
            dp[i]= res;
            return res;
    
        }
    }
    
    • 复杂度

      • 时间复杂度: O ( 2 n ) O(2^n) O(2n)
      • 空间复杂度: O ( n ) O(n) O(n)
递推
  • 实现

    class Solution {
    
        public int minHeightShelves(int[][] books, int shelfWidth) {
            int n = books.length;
            int[] dp = new int[n + 1];
            for (int i = 0; i < n; i++){
                int w = books[i][0], h = books[i][1];
                dp[i + 1] = dp[i] + h;// 独立一层
                for (int j = i - 1; j >= 0; j--){// 枚举可以选哪个
                    w += books[j][0];
                    if (w > shelfWidth) break;
                    h = Math.max(h, books[j][1]);
                    dp[i + 1] = Math.min(dp[i + 1], dp[j] + h);
                }
            }
            return dp[n];
        }
    }
    
    • 复杂度

      • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
      • 空间复杂度: O ( n ) O(n) O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值