leetcode5254:卖木头(二维dp)

题目描述:
给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 prices ,其中 prices[i] = [h_i, w_i, price_i] 表示你可以以 price_i 元的价格卖一块高为 h_i 宽为 w_i 的矩形木块。

每一次操作中,你必须按下述方式之一执行切割操作,以得到两块更小的矩形木块:
沿垂直方向按高度 完全 切割木块,或
沿水平方向按宽度 完全 切割木块
在将一块木块切成若干小木块后,你可以根据 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 的木块。
    思路:
    这样的过程显然是要用到动态规划的,主要是动态规划的状态定义和状态转移方程。
    状态定义:dp[i][j]就是i,j的木块最多可以赚到的钱数。
    状态转移:dp[i][j]可以是不分割直接买(这时必须在price中)否则有两种情况:
    沿着垂直方向切割和沿着竖直方向切割
class Solution:
    def sellingWood(self, m: int, n: int, prices: List[List[int]]) -> int:
        dp = [[0 for _ in range(n+1)] for _ in range(m+1)]
        d = {}
        for p in prices:
            d[(p[0], p[1])] = p[2]
        for i in range(m+1):
            for j in range(n+1):
                dp[i][j] = max(d.get((i, j), 0),
                               max(dp[k][j]+dp[i-k][j] for k in range(i//2+1)),   # 这里因为切割具有对称性,考虑一半就考虑完所有的情况了
                max(dp[i][o]+dp[i][j-o]for o in range(j//2+1)))
        return dp[m][n]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值