首页 > 其他分享 >【LeetCode 2312】卖木头块

【LeetCode 2312】卖木头块

时间:2024-03-15 13:00:43浏览次数:25  
标签:int max memo 2312 木头 long prices LeetCode dp

题目描述

原题链接: 2312 卖木头块

解题思路

  • 每次切割只能完全横切或者竖切,即切成更矮或者更窄的木块;
  • 每次切割后剩余的两部分木块都是更小规模的同类问题,典型的可以用动态规划求解的问题;
  • 具体到单个问题,高x宽y的木块能卖的最多钱数有三种情况:
    • prices数组中正好有对应宽高的价格,不用切割直接卖;
    • 上一刀横切,尝试找到使得[i, y]和[x - i, y]两个矮木块能卖钱数之和最大的i值, 即 $ MAX_{i=1}^{x/2} (dp[i][y] + dp[x - i][y]) $;
    • 上一刀竖切,尝试找到使得[x, i]与[x, y - i]两个窄木块能卖钱数之和最大的i值, 即 $ MAX_{i=1}^{y/2} (dp[x][i] + dp[x][y - i]) $。
  • 根据这三个情况进行记忆化递归处理规模由大到小的问题;或者从小到大按照状态转移方程求得DP数组值。

解题代码

  • 求解规模由大到小, 记忆化递归的解法:

      /**
       * 如果原始prices数组值用Map做哈希表,耗时会在500ms级别
       * 执行用时: 79 ms , 在所有 Java 提交中击败了 41.18% 的用户
       * 内存消耗: 49.92 MB , 在所有 Java 提交中击败了 76.47% 的用户
       */
      public long sellingWood(int m, int n, int[][] prices) {
          long[][] fullPrice = new long[m + 1][n + 1];
          for (int[] p : prices) {
              fullPrice[p[0]][p[1]] = p[2];
          }
          long[][] memo = new long[m + 1][n + 1];
          for (int i = 0; i <= m; i++) {
              Arrays.fill(memo[i], -1);
          }
          return process(m, n, fullPrice, memo);
      }
    
      private long process(int height, int width, long[][] fullPrice, long[][] memo) {
          if (memo[height][width] != -1) {
              return memo[height][width];
          }
          long ans = fullPrice[height][width];
          for (int i = 1; i <= (height >> 1); i++) {
              ans = Math.max(ans, process(i, width, fullPrice, memo) + process(height - i, width, fullPrice, memo));
          }
          for (int i = 1; i <= (width >> 1); i++) {
              ans = Math.max(ans, process(height, i, fullPrice, memo) + process(height, width - i, fullPrice, memo));
          }
          memo[height][width] = ans;
          return ans;
      }
    
  • 求解规模由小到大, 用状态转移方式求DP数组的解法:

      /**
       * 二维动态规划
       * 执行用时: 20 ms , 在所有 Java 提交中击败了 100.00% 的用户
       * 内存消耗: 50.77 MB , 在所有 Java 提交中击败了 23.53% 的用户
       */
      public long sellingWood(int m, int n, int[][] prices) {
          // dp[x][y]表示高为x宽为y的木块能卖的钱数最大值, prices包含的整块卖的金额是初始值
          long[][] dp = new long[m + 1][n + 1];
          for (int[] p : prices) {
              dp[p[0]][p[1]] = p[2];
          }
          for (int i = 1; i <= m; i++) {
              for (int j = 1; j <= n; j++) {
                  long max = dp[i][j];// 用临时变量而不是直接在第三层for循环内部直接更新dp[i][j],性能稍好些(直接更新的耗时是26ms)
                  for (int k = 1; k <= (i >> 1); k++) {
                      max = Math.max(max, dp[k][j] + dp[i - k][j]);
                  }
                  for (int k = 1; k <= (j >> 1); k++) {
                      max = Math.max(max, dp[i][k] + dp[i][j - k]);
                  }
                  dp[i][j] = max;
              }
          }
          return dp[m][n];
      }
    

标签:int,max,memo,2312,木头,long,prices,LeetCode,dp
From: https://www.cnblogs.com/coding-memory/p/18075156

相关文章

  • 代码随想录算法训练营第七天|LeetCode 344.反转字符串、541.反转字符串II、卡码网54.替
    344.反转字符串题目描述:​编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须**原地修改输入数组**、使用O(1)的额外空间解决这一问题。示例一:输入:s=["h","e","l","l","o"]输出:["o","l","l......
  • 代码随想录训练营第44天 | 动态规划:完全背包理论基础、​​​​​​LeetCode 518.零钱
    目录动态规划:完全背包理论基础文章讲解:代码随想录(programmercarl.com)视频讲解:带你学透完全背包问题!_哔哩哔哩_bilibili思路​​​​​​LeetCode518.零钱兑换II文章讲解:代码随想录(programmercarl.com)视频讲解:518.零钱兑换II_哔哩哔哩_bilibili思路​​​​​​Le......
  • leetcode 2.两数相加 ,链表
    2.两数相加给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字0之外,这两个数都不会以0 开头。 示例1:输入:l1=[2,4......
  • LeetCode题练习与总结:搜索旋转排序数组
    一、题目整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],...,nums[n-1],nums[0],nums[1],...,nums[k-1]](下标从0开始计数)。例如,[0,1,2,4,5,6,7]......
  • LeetCode题练习与总结:在排序数组中查找元素的第一个和最后一个位置
    一、题目给你一个按照非递减顺序排列的整数数组nums,和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值target,返回 [-1,-1]。你必须设计并实现时间复杂度为 O(logn) 的算法解决此问题。二、解题思路1.查找起始位置:使......
  • 『LeetCode』10. 正则表达式匹配 Regular Expression Matching
    题目描述给你一个字符串s和一个字符规律p,请你来实现一个支持'.'和'*'的正则表达式匹配。'.'匹配任意单个字符'*'匹配零个或多个前面的那一个元素所谓匹配,是要涵盖整个字符串s的,而不是部分字符串。示例1:输入:s="aa",p="a"输出:false解释:"a"无法匹配"aa"整个字......
  • LeetCodeHot100 73. 矩阵置零 54. 螺旋矩阵 48. 旋转图像 240. 搜索二维矩阵 II
    73.矩阵置零https://leetcode.cn/problems/set-matrix-zeroes/description/?envType=study-plan-v2&envId=top-100-likedpublicvoidsetZeroes(int[][]matrix){inttop=0,bottom=matrix.length,left=0,right=matrix[0].length;int[][]flag......
  • LeetCode232.栈实现队列
    ques:用两个栈实现队列功能ans:与225一样的思路,看完225大佬们的题解之后能很轻松的想出思路,用s1来实现真正模拟队列中的元素顺序,借助s2辅助完成这一排序代码实现#include<iostream>#include<stack>usingnamespacestd;classMyQueue{private:stack<int>s1;/......
  • leetcode.21 合并两个有序链表
     21.合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输......
  • [LeetCode] 2789. Largest Element in an Array after Merge Operations
    Youaregivena0-indexedarraynumsconsistingofpositiveintegers.Youcandothefollowingoperationonthearrayanynumberoftimes:Chooseanintegerisuchthat0<=i<nums.length-1andnums[i]<=nums[i+1].Replacetheelementnums......