赞
踩
给你两个整数 m
和 n
,分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 prices
,其中 prices[i] = [hi, wi, pricei]
表示你可以以 pricei
元的价格卖一块高为 hi
宽为 wi
的矩形木块。
每一次操作中,你必须按下述方式之一执行切割操作,以得到两块更小的矩形木块:
在将一块木块切成若干小木块后,你可以根据 prices
卖木块。你可以卖多块同样尺寸的木块。你不需要将所有小木块都卖出去。你 不能 旋转切好后木块的高和宽。
请你返回切割一块大小为 m x n
的木块后,能得到的 最多 钱数。
注意你可以切割木块任意次。
1. 可能会用不同切割方式得到相同尺寸的木块 ----> 可能要多次计算同一个尺寸的木块的最大收益 ----> 重叠子问题(将已经计算过的尺寸的木块的收益记录下来避免重复计算)
2. 求得到的最多钱 ----> 求能得到最多钱的切割方法 ----> 计算每一种尺寸(不超过m*n大小)的木块的最优切割方法
因此,动态规划适用于这个问题:动态规划(Dynamic Programming,简称DP)通常用于优化问题的求解。它通常用于解决具有重叠子问题和最优子结构性质的问题。使用动态规划解决问题需要考虑两个关键步骤:确定状态和状态转移方程。
因为我们需要切割木块以获得最大收益,所以状态用木块的尺寸表示,即木块的高度和宽度。定义一个二维数组 dp
,其中 dp[i][j]
表示切割一个大小为 i x j
的木块后能得到的最大收益。
对于尺寸为(x,y)的木块,考虑三种情况:
① 如果数组 prices
中存在 (x,y,price)
这一三元组,表示可以以 price
的价格卖出一个高为 x
、宽为 y
的矩形木块,则状态转移方程为:
dp[x][y] = price
② 如果 x > 1
,那么可以沿水平方向将木块切割成两部分,它们的高分别是 i
和 x - i
,宽为 y
。状态转移方程为:
dp[x][y] = max(dp[i][y] + dp[x - i][y] for i in range(1, x))
③ 如果 y > 1
,那么可以沿垂直方向将木块切割成两部分,它们的宽分别是 j
和 y - j
,高为 x
。状态转移方程为:
dp[x][y] = max(dp[x][j] + dp[x][y - j] for j in range(1, y))
代码如下:
- class Solution(object):
- def sellingWood(self, m, n, prices):
- """
- :type m: int
- :type n: int
- :type prices: List[List[int]]
- :rtype: int
- """
- # 构建哈希映射,键为木块的尺寸 (hi, wi),值为对应价格
- price_map = {}
- for hi, wi, price in prices:
- price_map[(hi, wi)] = price
-
- # 定义动态规划数组,dp[x][y]表示木块高为x、宽为y时的最大收益
- dp = [[0] * (n + 1) for _ in range(m + 1)]
-
- # 遍历每个可能的木块尺寸
- for x in range(1, m + 1):
- for y in range(1, n + 1):
- # 第一种情况:如果有对应的价格,直接取得最大收益
- if (x, y) in price_map:
- dp[x][y] = price_map[(x, y)]
- # 第二种情况:沿水平方向切割木块
- for i in range(1, x):
- dp[x][y] = max(dp[x][y], dp[i][y] + dp[x - i][y])
- # 第三种情况:沿垂直方向切割木块
- for j in range(1, y):
- dp[x][y] = max(dp[x][y], dp[x][j] + dp[x][y - j])
-
- return dp[m][n]

运行通过:
动态规划早就忘干净了...感谢gpt帮我想起来 ^_^
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。