0%

2312. 卖木头块

2312.卖木头块

题目描述:

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

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

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

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

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

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

数据范围:

$1\le m, n \le 200, 1\le prices.len \le 2\times 10^4$

题解:

直接设 $dp[i][j]$ 表示长度为 $i$ ,宽度为 $j$ 的木块卖完之后的最大价值。然后可以枚举切分这块木板,枚举横着切,竖着切。

四层循环。

需要使用 $hash$ 表记录一下目标木板。如果当前的 $i,j$ 是目标木板,直接更新一下价值,然后再枚举切分。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
struct PairHash
{
template <class T, class U>
size_t operator()(const pair<T, U> &p) const
{
return hash<T>()(p.first) ^ hash<U>()(p.second);
}
};
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const static long long mod = 1e9 + 7;
const long long INF_LL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;

long long sellingWood(int m, int n, vector<vector<int>> &prices)
{
vector<vector<long long>> dp(m + 1, vector<long long>(n + 1)); // 切割一块长宽为m,n的木块,最多能得到的钱数。
unordered_map<pair<int, int>, int, PairHash> mp;
for (auto &price : prices)
mp[{price[0], price[1]}] = price[2];
for (int i = 1; i <= m; ++i)
{
for (int j = 1; j <= n; ++j)
{
if (mp.count({i, j}))
dp[i][j] += mp[{i, j}];
for (int r = 1; r < i; ++r)
dp[i][j] = max(dp[i][j], dp[r][j] + dp[i - r][j]);
for (int c = 1; c < j; ++c)
dp[i][j] = max(dp[i][j], dp[i][c] + dp[i][j - c]);
}
}
return dp[m][n];
}
};