2024.3.15力扣每日一题——卖木头块

2024-04-04 17:44
文章标签 15 力扣 每日 木头 2024.3

本文主要是介绍2024.3.15力扣每日一题——卖木头块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2024.3.15

      • 题目来源
      • 我的题解
        • 方法一 记忆化搜索(自顶向下)
        • 方法二 动态规划(自底向上)

题目来源

力扣每日一题;题序:2312

我的题解

方法一 记忆化搜索(自顶向下)

用 f(x,y)表示当木块的高和宽分别是 x 和 y 时,可以得到的最多钱数。我们需要考虑三种情况:

  • 如果数组 prices 中存在 (x,y,price) 这一三元组,那么可以将木块以 prices 的价格卖出。为了快速判断存在性,可以使用一个哈希映射来进行存储,即哈希映射的键为 ( h i h_i hi, w i w_i wi),值为 p r i c e i price_i pricei ,这样就可以根据木块的高和宽,在 O(1) 的时间得到对应的价格。这种情况的状态转移方程为:
    f(x,y)=price。
  • 如果 x>1,那么可以沿水平方向将木块切成两部分,它们的高分别是 i ( 1 ≤ i < x ) i~(1 \leq i < x) i (1i<x)和 x−i,宽均为 y。因此可以得到状态转移方程:
    f ( x , y ) = max ⁡ 1 ≤ i < x { f ( i , y ) + f ( x − i , y ) } f(x, y) = \max_{1 \leq i < x} \big\{ f(i, y) + f(x-i, y) \big\} f(x,y)=max1i<x{f(i,y)+f(xi,y)}
  • 如果 y>1,那么可以沿垂直方向将木块切成两部分,它们的宽分别是 j ( 1 ≤ j < y ) j~(1 \leq j < y) j (1j<y) 和 y−j,高均为 x。因此可以得到状态转移方程:
    f ( x , y ) = max ⁡ 1 ≤ j < y { f ( x , j ) + f ( x , y − j ) } f(x, y) = \max_{1 \leq j < y} \big\{ f(x, j) + f(x, y-j) \big\} f(x,y)=max1j<y{f(x,j)+f(x,yj)}

当有多种情况满足时,我们需要选择它们中的较大值。最终的答案即为 f(m,n)。

时间复杂度:O(mn(m+n)+p),其中 p 是数组 prices的长度。
空间复杂度:O(mn+p),即为哈希映射和动态规划的数组需要使用的空间。

public long sellingWood(int m, int n, int[][] prices) {Map<String, Integer> value = new HashMap<>();for (int[] price : prices) {value.put(price[0]+"-"+price[1], price[2]);}//记忆化搜索的备忘录long[][] memo = new long[m + 1][n + 1];for (long[] row : memo) {Arrays.fill(row, -1);}return dfs(m, n, value, memo);
}public long dfs(int x, int y, Map<String, Integer> value, long[][] memo) {if (memo[x][y] != -1) {return memo[x][y];}String key = x+"-"+y;long ret = value.containsKey(key) ? value.get(key) : 0;if (x > 1) {//沿水平方向切for (int i = 1; i < x; i++) {ret = Math.max(ret, dfs(i, y, value, memo) + dfs(x - i, y, value, memo));}}if (y > 1) {//沿垂直方向切for (int j = 1; j < y; j++) {ret = Math.max(ret, dfs(x, j, value, memo) + dfs(x, y - j, value, memo));}}memo[x][y] = ret;return ret;
}
方法二 动态规划(自底向上)

时间复杂度:O( m 2 + n 2 + p m^2+n^2+p m2+n2+p)
空间复杂度:O(mn+p)

public long sellingWood(int m, int n, int[][] prices) {Map<String, Integer> value = new HashMap<>();for (int[] price : prices) {value.put(price[0] + "-" + price[1], price[2]);}long[][] dp = new long[m + 1][n + 1];for (int x = 1; x <= m; x++) {for (int y = 1; y <= n; y++) {String key = x + "-" + y;long ret = value.containsKey(key) ? value.get(key) : 0;if (x > 1) {// 沿水平方向切for (int i = 1; i < x; i++) {ret = Math.max(ret, dp[i][y] + dp[x - i][y]);}}if (y > 1) {// 沿垂直方向切for (int j = 1; j < y; j++) {ret = Math.max(ret, dp[x][j] + dp[x][y - j]);}}dp[x][y] = ret;}}return dp[m][n];
}

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~

这篇关于2024.3.15力扣每日一题——卖木头块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/876440

相关文章

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

每日一练7:简写单词(含链接)

1.链接 简写单词_牛客题霸_牛客网 2.题目 3.代码1(错误经验) #include <iostream>#include <string>using namespace std;int main() {string s;string ret;int count = 0;while(cin >> s)for(auto a : s){if(count == 0){if( a <=

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

Adblock Plus官方规则Easylist China说明与反馈贴(2015.12.15)

-------------------------------特别说明--------------------------------------- 视频广告问题:因Adblock Plus的局限,存在以下现象,优酷、搜狐、17173黑屏并倒数;乐视、爱奇艺播放广告。因为这些视频网站的Flash播放器被植入了检测代码,而Adblock Plus无法修改播放器。 如需同时使用ads

力扣第347题 前K个高频元素

前言 记录一下刷题历程 力扣第347题 前K个高频元素 前K个高频元素 原题目: 分析 我们首先使用哈希表来统计数字出现的频率,然后我们使用一个桶排序。我们首先定义一个长度为n+1的数组,对于下图这个示例就是长度为7的数组。为什么需要一个长度为n+1的数组呢?假如说总共有三个数字都为1,那么我们需要把这个1放在数组下标为3的位置,假如说数组长度为n,对于这个例子就是长度为3,那么它的