【记忆化搜索 】2312. 卖木头块

本文涉及知识点

记忆化搜索

LeetCode2312. 卖木头块

给你两个整数 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 * 10^4^

prices[i].length == 3

1 <= hi <= m

1 <= wi <= n

1 <= pricei <= 10^6^

所有 (hi, wi) 互不相同 。

记忆化搜索

vW1[h][w] 表示高为h,宽为w的木块,不切割能买的价格。为0表示无法买出。

vW[h][w] 表示最大卖出价格,0表示无法卖出,-1表示未处理。

状态转移(未处理):

垂直切:

wW[h][w] M a x x : 1 h − 1 ( M S ( x , w ) + M S ( h − x , w ) ) \large Max_{x:1}^{h-1}(MS(x,w)+MS(h-x,w)) Maxx:1h−1(MS(x,w)+MS(h−x,w))

水平切:

wW[h][w] M a x x : 1 w − 1 ( M S ( h , x ) + M S ( h , w − x ) ) \large Max_{x:1}^{w-1}(MS(h,x)+MS(h,w-x)) Maxx:1w−1(MS(h,x)+MS(h,w−x))

初始状态:vW为-1。

返回值:MS(h,w)。

代码

核心代码

cpp 复制代码
template<class ELE, class ELE2>
void MinSelf(ELE* seft, const ELE2& other)
{
	*seft = min(*seft, (ELE)other);
}

template<class ELE>
void MaxSelf(ELE* seft, const ELE& other)
{
	*seft = max(*seft, other);
}

class Solution {
public:
	long long sellingWood(int m, int n, vector<vector<int>>& prices) {
		m_vW1.assign(m + 1, vector<int>(n + 1));
		for (const auto& v : prices) {
			m_vW1[v[0]][v[1]] = v[2];
		}
		m_vW.assign(m + 1, vector<long long>(n + 1,-1));
		return MemorySeach(m, n);
	}
	long long MemorySeach(int m, int n) {
		auto& llRet = m_vW[m][n];
		if (-1 != llRet) { return llRet; }
		llRet = m_vW1[m][n];
		for (int h = 1; h < m; h++) {
			MaxSelf(&llRet, MemorySeach(h, n) + MemorySeach(m - h, n));
		}
		for (int w = 1; w < n;w++) {
			MaxSelf(&llRet, MemorySeach(m,w) + MemorySeach(m,n-w));
		}
		return llRet;
	}
	vector<vector<int>> m_vW1;
	vector<vector<long long>> m_vW;
};

VS自带的单元测试

cpp 复制代码
template<class T1,class T2>
void AssertEx(const T1& t1, const T2& t2)
{
	Assert::AreEqual(t1 , t2);
}

template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{
	Assert::AreEqual(v1.size(), v2.size());	
	for (int i = 0; i < v1.size(); i++)
	{
		Assert::AreEqual(v1[i], v2[i]);
	}
}

template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{
	sort(vv1.begin(), vv1.end());
	sort(vv2.begin(), vv2.end());
	Assert::AreEqual(vv1.size(), vv2.size());
	for (int i = 0; i < vv1.size(); i++)
	{
		AssertEx(vv1[i], vv2[i]);
	}
}

namespace UnitTest
{
	int m, n;
	vector<vector<int>> prices;
	TEST_CLASS(UnitTest)
	{
	public:
		TEST_METHOD(TestMethod0)
		{
			m = 3, n = 5, prices = { {1,4,2},{2,2,7},{2,1,3} };
			auto res = Solution().sellingWood(m, n, prices);
			AssertEx(19LL,res);
		}
		TEST_METHOD(TestMethod1)
		{
			m = 4, n = 6, prices = { {3,2,10},{1,4,2},{4,1,3} };
			auto res = Solution().sellingWood(m, n, prices);
			AssertEx(32LL, res);
		}
	};
}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

相关推荐
怀澈12242 分钟前
高性能服务器模型之Reactor(单线程版本)
linux·服务器·网络·c++
chnming19871 小时前
STL关联式容器之set
开发语言·c++
带多刺的玫瑰1 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
爱敲代码的憨仔1 小时前
《线性代数的本质》
线性代数·算法·决策树
威桑1 小时前
MinGW 与 MSVC 的区别与联系及相关特性分析
c++·mingw·msvc
熬夜学编程的小王1 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
yigan_Eins1 小时前
【数论】莫比乌斯函数及其反演
c++·经验分享·算法
Mr.132 小时前
什么是 C++ 中的初始化列表?它的作用是什么?初始化列表和在构造函数体内赋值有什么区别?
开发语言·c++
阿史大杯茶2 小时前
AtCoder Beginner Contest 381(ABCDEF 题)视频讲解
数据结构·c++·算法
C++忠实粉丝2 小时前
计算机网络socket编程(3)_UDP网络编程实现简单聊天室
linux·网络·c++·网络协议·计算机网络·udp