LeetCode 题解工作台

卖木头块

给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 prices ,其中 prices[i] = [h i , w i , price i ] 表示你可以以 price i 元的价格卖一块高为 h i 宽为 w i 的矩形木块。 每一次操作中,你必须按下述方式之一执行…

category

3

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 状态·转移·动态规划

bolt

答案摘要

我们先定义一个二维数组 ,其中 表示高为 ,宽为 的木块的价格。初始时,我们遍历价格数组 ,将每一块木块 $(h, w, p)$ 的价格 存入 中,其余价格为 。 然后我们设计一个函数 $dfs(h, w)$,表示对一块高为 ,宽为 的木块切割后能得到的最多钱数。答案就是 $dfs(m, n)$。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 prices ,其中 prices[i] = [hi, wi, pricei] 表示你可以以 pricei 元的价格卖一块高为 hi 宽为 wi 的矩形木块。

每一次操作中,你必须按下述方式之一执行切割操作,以得到两块更小的矩形木块:

  • 沿垂直方向按高度 完全 切割木块,或
  • 沿水平方向按宽度 完全 切割木块

在将一块木块切成若干小木块后,你可以根据 prices 卖木块。你可以卖多块同样尺寸的木块。你不需要将所有小木块都卖出去。你 不能 旋转切好后木块来交换它的高度值和宽度值。

请你返回切割一块大小为 m x n 的木块后,能得到的 最多 钱数。

注意你可以切割木块任意次。

 

示例 1:

输入:m = 3, n = 5, prices = [[1,4,2],[2,2,7],[2,1,3]]
输出:19
解释:上图展示了一个可行的方案。包括:
- 2 块 2 x 2 的小木块,售出 2 * 7 = 14 元。
- 1 块 2 x 1 的小木块,售出 1 * 3 = 3 元。
- 1 块 1 x 4 的小木块,售出 1 * 2 = 2 元。
总共售出 14 + 3 + 2 = 19 元。
19 元是最多能得到的钱数。

示例 2:

输入:m = 4, n = 6, prices = [[3,2,10],[1,4,2],[4,1,3]]
输出:32
解释:上图展示了一个可行的方案。包括:
- 3 块 3 x 2 的小木块,售出 3 * 10 = 30 元。
- 1 块 1 x 4 的小木块,售出 1 * 2 = 2 元。
总共售出 30 + 2 = 32 元。
32 元是最多能得到的钱数。
注意我们不能旋转 1 x 4 的木块来得到 4 x 1 的木块。

 

提示:

  • 1 <= m, n <= 200
  • 1 <= prices.length <= 2 * 104
  • prices[i].length == 3
  • 1 <= hi <= m
  • 1 <= wi <= n
  • 1 <= pricei <= 106
  • 所有 (hi, wi) 互不相同 。
lightbulb

解题思路

方法一:记忆化搜索

我们先定义一个二维数组 dd,其中 d[i][j]d[i][j] 表示高为 ii,宽为 jj 的木块的价格。初始时,我们遍历价格数组 pricesprices,将每一块木块 (h,w,p)(h, w, p) 的价格 pp 存入 d[h][w]d[h][w] 中,其余价格为 00

然后我们设计一个函数 dfs(h,w)dfs(h, w),表示对一块高为 hh,宽为 ww 的木块切割后能得到的最多钱数。答案就是 dfs(m,n)dfs(m, n)

函数 dfs(h,w)dfs(h, w) 的执行过程如下:

  • 如果 (h,w)(h, w) 已经被计算过了,直接返回答案。
  • 否则,我们先初始化答案为 d[h][w]d[h][w],然后枚举切割的位置,分别计算切割后的两块木块能得到的最多钱数,取最大值即可。

时间复杂度 (m×n×(m+n)+p)(m \times n \times (m + n) + p),空间复杂度 O(m×n)O(m \times n)。其中 pp 表示价格数组的长度,而 mmnn 分别表示木块的高和宽。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
    def sellingWood(self, m: int, n: int, prices: List[List[int]]) -> int:
        @cache
        def dfs(h: int, w: int) -> int:
            ans = d[h].get(w, 0)
            for i in range(1, h // 2 + 1):
                ans = max(ans, dfs(i, w) + dfs(h - i, w))
            for i in range(1, w // 2 + 1):
                ans = max(ans, dfs(h, i) + dfs(h, w - i))
            return ans

        d = defaultdict(dict)
        for h, w, p in prices:
            d[h][w] = p
        return dfs(m, n)
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Ability to efficiently solve dynamic programming problems with state transitions.

  • question_mark

    Understanding of memoization and how it optimizes recursive subproblem solutions.

  • question_mark

    Proficiency in iterating through all possible subproblems to determine optimal solutions.

warning

常见陷阱

外企场景
  • error

    Failing to consider both vertical and horizontal cuts at each step.

  • error

    Not using memoization, which leads to redundant calculations and increased time complexity.

  • error

    Overlooking the fact that you cannot rotate the wood pieces, which could affect the available dimensions.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Problem with larger dimensions and increased number of price entries.

  • arrow_right_alt

    Variation with added constraints on how many times each piece can be sold.

  • arrow_right_alt

    Adjusted problem where you need to minimize the total number of cuts.

help

常见问题

外企场景

卖木头块题解:状态·转移·动态规划 | LeetCode #2312 困难