【动态规划 区间dp 位运算】3117. 划分数组得到最小的值之和

news2025/1/12 12:08:34

本文涉及知识点

动态规划 区间dp 位运算

LeetCode3117. 划分数组得到最小的值之和

给你两个数组 nums 和 andValues,长度分别为 n 和 m。
数组的 值 等于该数组的 最后一个 元素。
你需要将 nums 划分为 m 个 不相交的连续 子数组,对于第 ith 个子数组 [li, ri],子数组元素的按位AND运算结果等于 andValues[i],换句话说,对所有的 1 <= i <= m,nums[li] & nums[li + 1] & … & nums[ri] == andValues[i] ,其中 & 表示按位AND运算符。
返回将 nums 划分为 m 个子数组所能得到的可能的 最小 子数组 值 之和。如果无法完成这样的划分,则返回 -1 。
示例 1:
输入: nums = [1,4,3,3,2], andValues = [0,3,3,2]
输出: 12
解释:
唯一可能的划分方法为:
[1,4] 因为 1 & 4 == 0
[3] 因为单元素子数组的按位 AND 结果就是该元素本身
[3] 因为单元素子数组的按位 AND 结果就是该元素本身
[2] 因为单元素子数组的按位 AND 结果就是该元素本身
这些子数组的值之和为 4 + 3 + 3 + 2 = 12
示例 2:

输入: nums = [2,3,5,7,7,7,5], andValues = [0,7,5]

输出: 17

解释:

划分 nums 的三种方式为:

[[2,3,5],[7,7,7],[5]] 其中子数组的值之和为 5 + 7 + 5 = 17
[[2,3,5,7],[7,7],[5]] 其中子数组的值之和为 7 + 7 + 5 = 19
[[2,3,5,7,7],[7],[5]] 其中子数组的值之和为 7 + 7 + 5 = 19
子数组值之和的最小可能值为 17

示例 3:

输入: nums = [1,2,3,4], andValues = [2]

输出: -1

解释:

整个数组 nums 的按位 AND 结果为 0。由于无法将 nums 划分为单个子数组使得元素的按位 AND 结果为 2,因此返回 -1。
提示:
1 <= n == nums.length <= 104
1 <= m == andValues.length <= min(n, 10)
1 <= nums[i] < 105
0 <= andValues[j] < 105

动态规划的位运算

f(i,j) = & = x : i j \Large\And=_{x:i}^j &=x:ij
vNext[cur] 记录符合以下条件之一的next:
一,next-1 < cur。
二,f(i,next) ≠ \neq = f(i,next-1)。
iBitCnt = log(max(nums[i]) ≈ \approx 22 ,显然next的数量不会超过iBitCnt。
如果f(i,j)发生变化,至少一个二进制1变成0。

动态规划

动态规划的状态表示

dp[len][cur] 表示将nums[0…cur]划分为len个区间的最小和。
空间复杂度:O(nm)

动态规划的转移方程

r个区间向r+1个区间转移时:
如果f(cur,next) 等于 andValues[r-1]则:
MinSelf(dp[r+1][x],dp[r][cur-1]+nums[x]) x ∈ [ n e x t , n e x t 的下一个值 ) 这样值设置的时间复杂度是: \in[next,next的下一个值) 这样值设置的时间复杂度是: [next,next的下一个值)这样值设置的时间复杂度是: O ( m × n × i B i t C n t × n ) O(m \times n \times iBitCnt \times n ) O(m×n×iBitCnt×n) ,超时了。
只更新:x = next,其它的用二种方式更新:
如果 (nums[cur]& andValues[r-1]) = andValues[r-1]
则MinSelf(dp[r][cur],dp[r][cur-1])
时间复杂度:$ O ( m × n × i B i t C n t ) O(m \times n \times iBitCnt ) O(m×n×iBitCnt)

动态规划的初始值

枚举第一个区间

动态规范的返回值

dp.back().back()

动态规划的填表顺序

len 从1到m_r-1。
cur从1到m_c-1

代码

核心代码

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:
	int minimumValueSum(vector<int>& nums, vector<int>& andValues) {
		const int iBitCnt = 22;
		m_r = andValues.size();
		m_c = nums.size();
		const int iMax = (1 << iBitCnt) - 1;
		vector<vector<int>> dp(m_r+1,vector<int>(m_c, m_iNotMay));
		int iAnd = iMax;
		for (int i = 0; i < m_c; i++) {
			iAnd &= nums[i];
			if (iAnd == andValues[0]) {
				dp[1][i] = nums[i];
			}
		}
		vector<set<int>> vNext(m_c);
		{
			vector<int> next(iBitCnt, m_c);
			for (int i = nums.size() - 1; i >= 0; i--) {
				vNext[i] = set<int>(next.begin(), next.end());
				vNext[i].emplace(i);
				vNext[i].erase(m_c);
				for (int bit = 0; bit < iBitCnt; bit++)
				{
					bool b = (1 << bit) & nums[i];
					if (!b) {
						next[bit] = i;
					}
				}
			}
		}
		for (int r = 1; r < m_r; r++)
		{
			for (int cur = 1; cur < m_c; cur++)
			{
				int iAdd = iMax;
				for (const auto& next : vNext[cur]) {
					iAdd &= nums[next];
					if (andValues[r] == iAdd) {
						MinSelf(&dp[r + 1][next], dp[r][cur - 1] + nums[next]);
					}
				}
				if ((andValues[r - 1] & nums[cur]) == andValues[r - 1]) {
					MinSelf(&dp[r][cur], dp[r][cur - 1]+nums[cur]-nums[cur-1]);
				}				
			}			
		}
		{
			int r = m_r;
			for (int cur = 1; cur < m_c; cur++)
			{				
				if ((andValues[r - 1] & nums[cur]) == andValues[r - 1]) {
					MinSelf(&dp[r][cur], dp[r][cur - 1] + nums[cur] - nums[cur - 1]);
				}
			}
		}
		const int iRet = dp.back().back();
		return (iRet >= 1'000'000) ? -1 : iRet;
	}
	int m_r,m_c;
	const int m_iNotMay = 1'000'000'000;
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{

	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}

}

int main()
{
	vector<int>  nums, andValues;
	int k;

	{
		Solution sln;
		nums = { 1, 9, 8, 8 }, andValues = { 1,8 };
		auto res = sln.minimumValueSum(nums, andValues);
		Assert(9, res);
	}
	{
		Solution sln;
		nums = { 1, 3, 2, 4, 7, 5, 3 }, andValues = { 0, 5, 3 };
		auto res = sln.minimumValueSum(nums, andValues);
		Assert(12, res);
	}
	{
		Solution sln;
		nums = { 1, 4, 3, 3, 2 }, andValues = { 0, 3, 3, 2 };
		auto res = sln.minimumValueSum(nums, andValues);
		Assert(12, res);
	}

	//vector<int>  nums = { 3,6,9 };
	//int k;
	//
	//{
	//	Solution sln;
	//	nums = { 3,6,9 }, k = 3;
	//	auto res = sln.findKthSmallest(nums, k);
	//	Assert(9LL, 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++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1609481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vscode设置conda默认python环境,简单有效

本地conda 可能安装了各种环境&#xff0c;默认的vscode总是base环境&#xff0c;这时你想要在vscode调试python代码&#xff0c;使用默认的环境没有安装对应的包就会遇到报错解决这个问题的方法很简单ctrlshiftp 调出命令面板 再输入 select interpreter , 选择 python 选择解…

在Spring Boot中使用POI完成一个excel报表导入数据到MySQL的功能

最近看了自己玩过的很多项目&#xff0c;忽然发现有一个在实际开发中我们经常用到的功能&#xff0c;但是我没有正儿八经的玩过这个功能&#xff0c;那就是在Spring Boot中实现一个excel报表的导入导出功能&#xff0c;这篇博客&#xff0c;主要是围绕excel报表数据导入进行&am…

一例Mozi僵尸网络的挖矿蠕虫分析(workminer)

概述 这是一个Linux平台的挖矿蠕虫&#xff0c;使用了go和C混合编译而成&#xff0c;主要通过爆破SSH口令进行传播&#xff0c;属于Mozi僵尸网络。其中GO代码负责SSH相关的爆破传播&#xff0c;以及对Config的处理&#xff0c;C代码则负责处理加入Mozi P2P网络&#xff0c;拉取…

c++11 标准模板(STL)本地化库 - 平面类别(std::collate) - 定义字典序比较和字符串的散列(二)

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 定义字典序比较和字符串的散列 std::collate 类 std::collate 封…

Redis的Stream 和 实现队列的方式【List、SortedSet、发布订阅、Stream、Java】

Redis队列与Stream、Redis 6多线程详解 Redis队列与StreamStream总述常用操作命令生产端消费端单消费者消费组消息消费 Redis队列几种实现的总结基于List的 LPUSHBRPOP 的实现基于Sorted-Set的实现PUB/SUB&#xff0c;订阅/发布模式基于Stream类型的实现与Java的集成 消息队列问…

MySQL高级(索引-性能分析-profile)

show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪去了。通过 have_profiling参数&#xff0c;能够看到当前MySQL 是否支持 profile 操作&#xff1a; select have_profiling 默认 profiling 是关闭的 select profiling; 可以通过 set 语句在 session / global 级…

【python】flask操作数据库工具SQLAlchemy,详细用法和应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

萌新_1 环境安装(基于QQNT框架 Python Flask)

遇到问题加QQ群聊 群主在线解答 点击加入群聊【星辰开发】 一&#xff1a;安装QQ 目前为开发&#xff0c;推荐都安装到一台电脑上 直接安装到本地windows电脑&#xff0c; 优点方便开发 一键安装 Windows 用户一键安装方案 https://github.com/super1207/install_llob/rel…

从零到一品牌电商私域流量代运营规划方案

【干货资料持续更新&#xff0c;以防走丢】 从零到一品牌电商私域流量代运营规划方案 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PPT共50页&#xff08;完整资料包含以下内容&#xff09; 目录 私域运营方案&#xff1a; 一、项目背景与目标 - 开创数智化…

kaggle电子邮件分类xgboost建模可视化模型评估混淆矩阵范例

目录 概述 依赖环境 代码解读 库的导入 数据读取 扇形图可视化统计 词云图可视化 分布条形图可视化 数据预处理 划分数据集 模型训练 模型预测和评估 ROC曲线评估 混淆矩阵评估 多维度交叉评估 配套源码和数据集 xgboost邮件分类配套数据集和源码下载地址 概述…

RK3568 学习笔记 : u-boot 千兆网络功能验证

前言 开发板型号&#xff1a; 【正点原子】 的 RK3568 开发板 使用 虚拟机 ubuntu 20.04 编译 RK3568 Linux SDK&#xff0c;生成镜像&#xff0c;烧写后&#xff0c;Linux 系统正常启动 开启后可以使用 CTRLC 进入 u-boot 本篇验证一下 u-boot 下网络功能 【正点原子】 rk…

OpenHarmony 视图缩放组件—subsampling-scale-image-view

简介 深度缩放视图&#xff0c;图像显示&#xff0c;手势平移缩放双击等 效果图&#xff08;旋转、缩放、平移&#xff09; 下载安装 ohpm install ohos/subsampling-scale-image-view OpenHarmony ohpm 环境配置等更多内容&#xff0c;请参考如何安装 OpenHarmony ohpm 包 使…

【Linux C | 多线程编程】线程同步 | 信号量(无名信号量) 及其使用例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

先撸清楚:并发/并行、单线程/多线程、同步/异步

前言 在编码的过程中经常会遇到并发/并行、同步/异步、单线程/多线程等术语&#xff0c;在分析JS setTimeout/Promise之前先把这些概念厘清。 通过本篇文章&#xff0c;你将了解&#xff1a; 并发/并行的概念及区别同步/异步的概念及区别单线程/多线程的概念及区别主线程和子线…

Next App Router(中)

1.定义布局 布局是指多个页面共享的 UI。在导航的时候&#xff0c;布局会保留状态、保持可交互性并且不会重新渲染&#xff0c;比如用来实现后台管理系统的侧边导航栏。 定义一个布局&#xff0c;你需要新建一个名为 layout.js的文件&#xff0c;该文件默认导出一个 React 组…

XUbuntu18.04 源码编译Qt4.5.3的过程

由于新公司很多旧的软件都是基于这个版本做的嵌入式开发。 所以想要自己搭一套基于Linux的非嵌入式开发环境&#xff0c;方便用来调试和编译代码。 这样就可以完成在linux下开发&#xff0c;然后直接嵌入式打包&#xff0c;涉及到界面的部分就不需要上机调试看问题了。 所以…

一个完全用rust写的开源操作系统-Starry

1. Starry Starry是2023年全国大学生计算机系统能力大赛操作系统设计赛-内核实现赛的二等奖作品。Starry是在组件化OS的arceos的基础上&#xff0c;进行二次开发的操作系统内核&#xff0c;使用宏内核架构&#xff0c;能够运行Linux应用的内核。 原始的操作系统大赛的仓库为 …

linux 基础命令docker及防火墙iptables详解

应用场景&#xff1a; web应用自动打包和发布 自动化测试&#xff0c;持续集成、发布 在服务环境中部署后台应用 搭建paaS平台 安装应用 apt install docker.io#kali中 配置docker源&#xff0c;文件位置/etc/docker/daemon.json { "registry-mirrors": [ "h…

原牛角源码(修罗bbs)全站程序打包带数据库备份

原牛角源码(修罗bbs)全站程序打包带数据库备份&#xff0c;牛角源码全站数据全站文件、插件打包分享给大家&#xff0c;有兴趣的可以搭建玩玩&#xff01; conf文件夹中自己配置conf.php里面的数据库链接文件&#xff0c;默认管理账号&#xff1a;admin&#xff0c;密码&#…

【大数据】bigtable,分布式数据库的鼻祖

目录 1.概述 2.数据模型 3.API 4.架构 5.一个完整的读写过程 6.如何查找到要的tablet 7.LSM树 1.概述 本文是作者阅读完bigtable论文后对bigtable进行的一个梳理&#xff0c;只涉及核心概念不涉及具体实操&#xff0c;具体实操会在后续的文章中推出。 GFS的出现虽然解…