当前位置: 首页 > news >正文

leetcode 1937. 扣分后的最大得分「动态规划」「拆项」

1937. 扣分后的最大得分

题目描述:

给你一个n*m的整数矩阵ar,一开始你的得分为0,你想最大化从矩阵中得到的分数

你的得分方式为:每一行 中选取一个格子,选中坐标为 (r, c) 的格子会给你的总得分 增加 points[r][c]

然而,相邻行之间被选中的格子如果隔得太远,你会失去一些得分。对于相邻行 rr + 1 (其中 0 <= r < m - 1),选中坐标为 (r, c1)(r + 1, c2) 的格子,你的总得分 减少 abs(c1 - c2)

请你返回你能得到的 最大 得分

思路:

很经典的拆项思路

d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i − 1 i-1 i1行均选择了一个格子,第 i i i行选了第 j j j个格子,获得的最大价值

很显然状态要从上一行转移过来

  • d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , a r [ i ] [ j ] + d p [ i − 1 ] [ k ] − a b s ( k − j ) ) dp[i][j] = max(dp[i][j], ar[i][j] + dp[i - 1][k] - abs(k - j)) dp[i][j]=max(dp[i][j],ar[i][j]+dp[i1][k]abs(kj))

如果这样暴力转移,则时间复杂度是 O ( n ∗ m ∗ m ) O(n*m*m) O(nmm),一定会超时的

我们考虑拆项,根据 k k k j j j的大小,分情况讨论

  • d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , t r [ i ] [ j ] + ( d p [ i − 1 ] [ k ] + k ) − j ) , k < = j dp[i][j] = max(dp[i][j], tr[i][j] + (dp[i-1][k] + k) - j), k <= j dp[i][j]=max(dp[i][j],tr[i][j]+(dp[i1][k]+k)j),k<=j
  • d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , t r [ i ] [ j ] + ( d p [ i − 1 ] [ k ] − k ) + j ) , k > j dp[i][j] = max(dp[i][j], tr[i][j] + (dp[i-1][k] - k) + j), k > j dp[i][j]=max(dp[i][j],tr[i][j]+(dp[i1][k]k)+j),k>j

对于 d p [ i ] [ j ] dp[i][j] dp[i][j]我们如果可以用 O ( 1 ) O(1) O(1)的时间得到 m a x { d p [ i − 1 ] [ k ] + k } , k < = j max\{dp[i-1][k] + k\},k<=j max{dp[i1][k]+k},k<=j m a x { d p [ i − 1 ] [ k ] − k } max\{dp[i-1][k]-k\} max{dp[i1][k]k}的值就行了

所以我们记录一个前缀最大值数组和一个后缀最大值数组,分别记录即可

同时,我们可以发现转移的时候只和上一维度的值有关,可以用滚动数组优化空间

所以最后的时间复杂度是 O ( n ∗ m ) O(n*m) O(nm)

class Solution {
public:long long maxPoints(vector<vector<int>>& tr) {int n = tr.size(), m = tr[0].size();vector<long long>dp(m + 1);vector<long long>pre(m + 2), suf(m + 2);for(int j = 1; j <= m + 1; ++j){pre[j] = j;suf[j] = -j;}for(int i = 1; i <= n; ++i){   for(int j = 1; j <= m; ++j){dp[j] = tr[i - 1][j - 1] + max(pre[j] - j, suf[j + 1] + j);}for(int j = 1; j <= m; ++j){pre[j] = max(pre[j - 1], dp[j] + j);}for(int j = m; j >= 1; --j){suf[j] = max(suf[j + 1], dp[j] - j);}}long long ans = 0;for(int i = 1; i <= m; ++i)ans = max(ans, dp[i]);return ans;}
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Symfony 表单构建器:创建和管理表单的最佳实践
  • 通过 WSL 2 在Windows 上挂载 Linux 磁盘
  • 【Linux C | 网络编程】进程池退出的实现详解(五)
  • Object.entries()解析出来的数组顺序乱了,健是string类型
  • 传统自然语言处理(NLP)与大规模语言模型(LLM)详解
  • 区块链——hardhat使用
  • AndroidStudio 开发环境搭建
  • 全球相机控制面板市场展望与未来增长机遇:预计未来六年年复合增长率CAGR为4.3%
  • uniapp中出现图片过小会与盒子偏离
  • RDF中IEXT和ICEXT的区别
  • [240727] Qt Creator 14 发布 | AMD 推迟 Ryzen 9000芯片发布
  • Redis:RDB持久化
  • 2024 微信小程序 学习笔记 第二天
  • Spring Boot自动装配原理
  • MongoDB - 聚合阶段 $group 的使用
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • Electron入门介绍
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • go append函数以及写入
  • java中具有继承关系的类及其对象初始化顺序
  • js作用域和this的理解
  • Laravel 菜鸟晋级之路
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • nginx 负载服务器优化
  • Node + FFmpeg 实现Canvas动画导出视频
  • REST架构的思考
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • Travix是如何部署应用程序到Kubernetes上的
  • 如何设计一个微型分布式架构?
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 阿里云ACE认证之理解CDN技术
  • 交换综合实验一
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • #define用法
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • $$$$GB2312-80区位编码表$$$$
  • (1)Android开发优化---------UI优化
  • (2020)Java后端开发----(面试题和笔试题)
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)Scala的“=”符号简介
  • (转)一些感悟
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .net 4.0发布后不能正常显示图片问题
  • .Net mvc总结
  • .net 生成二级域名