leetcode
leetcode 2651 ~ 2700
卖木头块

卖木头块

难度:

标签:

题目描述

You are given two integers m and n that represent the height and width of a rectangular piece of wood. You are also given a 2D integer array prices, where prices[i] = [hi, wi, pricei] indicates you can sell a rectangular piece of wood of height hi and width wi for pricei dollars.

To cut a piece of wood, you must make a vertical or horizontal cut across the entire height or width of the piece to split it into two smaller pieces. After cutting a piece of wood into some number of smaller pieces, you can sell pieces according to prices. You may sell multiple pieces of the same shape, and you do not have to sell all the shapes. The grain of the wood makes a difference, so you cannot rotate a piece to swap its height and width.

Return the maximum money you can earn after cutting an m x n piece of wood.

Note that you can cut the piece of wood as many times as you want.

 

Example 1:

Input: m = 3, n = 5, prices = [[1,4,2],[2,2,7],[2,1,3]]
Output: 19
Explanation: The diagram above shows a possible scenario. It consists of:
- 2 pieces of wood shaped 2 x 2, selling for a price of 2 * 7 = 14.
- 1 piece of wood shaped 2 x 1, selling for a price of 1 * 3 = 3.
- 1 piece of wood shaped 1 x 4, selling for a price of 1 * 2 = 2.
This obtains a total of 14 + 3 + 2 = 19 money earned.
It can be shown that 19 is the maximum amount of money that can be earned.

Example 2:

Input: m = 4, n = 6, prices = [[3,2,10],[1,4,2],[4,1,3]]
Output: 32
Explanation: The diagram above shows a possible scenario. It consists of:
- 3 pieces of wood shaped 3 x 2, selling for a price of 3 * 10 = 30.
- 1 piece of wood shaped 1 x 4, selling for a price of 1 * 2 = 2.
This obtains a total of 30 + 2 = 32 money earned.
It can be shown that 32 is the maximum amount of money that can be earned.
Notice that we cannot rotate the 1 x 4 piece of wood to obtain a 4 x 1 piece of wood.

 

Constraints:

  • 1 <= m, n <= 200
  • 1 <= prices.length <= 2 * 104
  • prices[i].length == 3
  • 1 <= hi <= m
  • 1 <= wi <= n
  • 1 <= pricei <= 106
  • All the shapes of wood (hi, wi) are pairwise distinct.

代码结果

运行时间: 145 ms, 内存: 21.7 MB


/*
题目思路:
1. 我们需要动态规划来解决这个问题。使用一个二维数组dp,其中dp[i][j]表示高度为i,宽度为j的矩形能得到的最多钱数。
2. 初始化dp数组,dp[i][j] = 0,因为如果没有prices提供的木块,这些大小的矩形是不能卖钱的。
3. 对于每一个给定的木块尺寸和价格,更新dp数组的相应位置。
4. 尝试所有可能的切割方法,不断更新dp数组。
5. 最终结果保存在dp[m][n]中。
*/

import java.util.Arrays;

public class Solution {
    public int maxSellingPrice(int m, int n, int[][] prices) {
        int[][] dp = new int[m + 1][n + 1];
        Arrays.stream(prices).forEach(price -> dp[price[0]][price[1]] = price[2]);
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                for (int k = 1; k <= i / 2; k++) {
                    dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]);
                }
                for (int k = 1; k <= j / 2; k++) {
                    dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]);
                }
            }
        }
        return dp[m][n];
    }
}

解释

方法:

此题采用动态规划的方法来解决。定义 dp[x][y] 为当木块尺寸为 x 高和 y 宽时可以获得的最大收益。初始化 dp 数组时,先将所有给定的价格设置到对应的尺寸上。接下来,对于每个尺寸的木块,尝试进行水平和垂直的切割,更新 dp[x][y] 为所有可能的切割方式中的最大值。通过维护 optimized_split_height_per_width 和 optimized_split_width_per_height 两个列表来记录对于每个尺寸的木块,之前有效的切割位置,从而减少不必要的重复计算,优化动态规划过程。最终 dp[m][n] 存储的就是切割大小为 m x n 的木块能得到的最多钱数。

时间复杂度:

O(m^2 * n + m * n^2)

空间复杂度:

O(m * n)

代码细节讲解

🦆
在动态规划解决方案中,为什么需要维护optimized_split_height_per_width和optimized_split_width_per_height两个列表,它们具体的作用是什么?
这两个列表的目的是为了存储之前有效的切割位置,从而减少不必要的重复计算。在动态规划中,每次尝试切割一个木块时,不需要遍历所有可能的切割位置,而是只考虑之前已经证明能提供最大收益的切割位置。这样做可以优化动态规划的过程,提高算法的效率。例如,如果在某个尺寸的木块中,某一切割位置未曾提供超越已知最大收益的新收益,则在后续相同的切割尝试中可以忽略这个切割位置。
🦆
动态规划表dp[x][y]的初始化过程中,如果存在多个价格条目针对同一尺寸(hi, wi),例如两个不同的价格,该如何处理?
在初始化dp表时,如果存在多个价格条目针对同一尺寸,应该选择最高的价格设置到dp表中。这是因为我们的目标是最大化收益,因此对于同一尺寸的木块,应当采用能够获得最大收益的价格。在代码中,可以通过比较当前价格与dp表中已存储的价格,选择较大者进行更新。
🦆
您在更新dp表时,考虑了水平和垂直切割,但是如何确保这些切割总是导致最优解?是否存在某些情况下无法通过当前的切割方式达到最大收益?
在动态规划中通过考虑所有可能的水平和垂直切割,我们尝试找到任何可能的方式来最大化收益。理论上,通过穷尽这些切割方式,我们能够确保找到最优解。然而,动态规划的前提是基于'最优子结构'的假设——即问题的最优解包含了其子问题的最优解。如果这个假设成立,我们的方法总是能找到最优解。不过,如果存在某些特殊情况或约束(例如价格不规则或者受限的切割规则),那么可能需要对算法进行调整或增加额外的逻辑来处理这些特殊情况。

相关问题