【状态机动态规划 状态压缩】1434. 每个人戴不同帽子的方案数

news2024/11/15 18:48:04

本文涉及知识点

位运算、状态压缩、枚举子集汇总
动态规划汇总

LeetCode 1434. 每个人戴不同帽子的方案数

总共有 n 个人和 40 种不同的帽子,帽子编号从 1 到 40 。
给你一个整数列表的列表 hats ,其中 hats[i] 是第 i 个人所有喜欢帽子的列表。
请你给每个人安排一顶他喜欢的帽子,确保每个人戴的帽子跟别人都不一样,并返回方案数。
由于答案可能很大,请返回它对 10^9 + 7 取余后的结果。
示例 1:
输入:hats = [[3,4],[4,5],[5]]
输出:1
解释:给定条件下只有一种方法选择帽子。
第一个人选择帽子 3,第二个人选择帽子 4,最后一个人选择帽子 5。
示例 2:
输入:hats = [[3,5,1],[3,5]]
输出:4
解释:总共有 4 种安排帽子的方法:
(3,5),(5,3),(1,3) 和 (1,5)
示例 3:
输入:hats = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
输出:24
解释:每个人都可以从编号为 1 到 4 的帽子中选。
(1,2,3,4) 4 个帽子的排列方案数为 24 。
示例 4:
输入:hats = [[1,2,3],[2,3,5,6],[1,3,7,9],[1,8,9],[2,5,7]]
输出:111
提示:
n == hats.length
1 <= n <= 10
1 <= hats[i].length <= 40
1 <= hats[i][j] <= 40
hats[i] 包含一个数字互不相同的整数列表。

动态规划

预处理

hatToPeo 记录 帽子被那些人喜欢。帽子和人都从0开始。

动态规划状态表示

dp’[i][j]表示处理前i个帽子,j表示那些人已经分配了帽子。(1<<x )& j 表示第x个人是否分配了帽子。
pre[j] = dp’[i][j] dp[j] = dp’[i][j]
如果不用滚动向量,时间复杂度:O(m2n)
如果记录帽子被分配的状态,空间复杂度至少是O(2m)严重超时。

动态规划的转移方程

对于每种状态,只有n+1种后置状态。任何人都不戴此帽子,枚举每个人戴帽子。单状态转移方程的时间复杂度是O(n)。
故总时间复杂度:O(m2nn)

动态规划的初始状态

pre[0][0] = 1 ,其它为0。

动态规划的填表顺序

i = 0 to m-1

动态规划的返回值

pre.back()

代码

核心代码

template<int MOD = 1000000007>
class C1097Int
{
public:
	C1097Int(long long llData = 0) :m_iData(llData% MOD)
	{

	}
	C1097Int  operator+(const C1097Int& o)const
	{
		return C1097Int(((long long)m_iData + o.m_iData) % MOD);
	}
	C1097Int& operator+=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData + o.m_iData) % MOD;
		return *this;
	}
	C1097Int& operator-=(const C1097Int& o)
	{
		m_iData = (m_iData + MOD - o.m_iData) % MOD;
		return *this;
	}
	C1097Int  operator-(const C1097Int& o)
	{
		return C1097Int((m_iData + MOD - o.m_iData) % MOD);
	}
	C1097Int  operator*(const C1097Int& o)const
	{
		return((long long)m_iData * o.m_iData) % MOD;
	}
	C1097Int& operator*=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData * o.m_iData) % MOD;
		return *this;
	}
	C1097Int  operator/(const C1097Int& o)const
	{
		return *this * o.PowNegative1();
	}
	C1097Int& operator/=(const C1097Int& o)
	{
		*this /= o.PowNegative1();
		return *this;
	}
	bool operator==(const C1097Int& o)const
	{
		return m_iData == o.m_iData;
	}
	bool operator<(const C1097Int& o)const
	{
		return m_iData < o.m_iData;
	}
	C1097Int pow(long long n)const
	{
		C1097Int iRet = 1, iCur = *this;
		while (n)
		{
			if (n & 1)
			{
				iRet *= iCur;
			}
			iCur *= iCur;
			n >>= 1;
		}
		return iRet;
	}
	C1097Int PowNegative1()const
	{
		return pow(MOD - 2);
	}
	int ToInt()const
	{
		return m_iData;
	}
private:
	int m_iData = 0;;
};


class Solution {
public:
	int numberWays(vector<vector<int>>& hats) {
		const int N = hats.size();
		vector<vector<int>> hatToPeo(40);
		for (int peo = 0; peo < hats.size(); peo++) {
			for (const auto& hat : hats[peo]) {
				hatToPeo[hat - 1].emplace_back(peo);
			}
		}
		vector<C1097Int<>> pre(1 << N);
		pre[0] = 1;
		for (int i = 0; i < 40; i++) {
			auto dp = pre;//本帽子不选择	
			for (int j = 0; j < (1 << N); j++  ) {
				for (const auto& peo : hatToPeo[i]) {
					if (j & (1 << peo)) { continue; }
					dp[j | (1 << peo)] += pre[j];
				}
			}	
			pre.swap(dp);
		}
		return pre.back().ToInt();
	}
};

单元测试

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
{
	vector<vector<int>> hats;
	TEST_CLASS(UnitTest)
	{
	public:
		TEST_METHOD(TestMethod0)
		{
			hats = { {3,4},{4,5},{5} };
			auto res = Solution().numberWays(hats);
			AssertEx(1, res);
		}
		TEST_METHOD(TestMethod1)
		{
			hats = { {3,5,1},{3,5} };
			auto res = Solution().numberWays(hats);
			AssertEx(4, res);
		}
		TEST_METHOD(TestMethod2)
		{
			hats = { {1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4} };
			auto res = Solution().numberWays(hats);
			AssertEx(24, res);
		}
		TEST_METHOD(TestMethod3)
		{
			hats = { {1,2,3},{2,3,5,6},{1,3,7,9},{1,8,9},{2,5,7} };
			auto res = Solution().numberWays(hats);
			AssertEx(111, res);
		}
		TEST_METHOD(TestMethod4)
		{
			hats = { {1,3,5,10,12,13,14,15,16,18,19,20,21,27,34,35,38,39,40},{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40},{3,7,10,12,13,14,15,17,21,25,29,31,35,40},{2,3,7,8,9,11,12,14,15,16,17,18,19,20,22,24,25,28,29,32,33,34,35,36,38},{6,12,17,20,22,26,28,30,31,32,34,35},{1,4,6,7,12,13,14,15,21,22,27,28,30,31,32,35,37,38,40},{6,12,21,25,38},{1,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40} };
			auto res = Solution().numberWays(hats);
			AssertEx(842465346, res);
		}
	};
}

扩展阅读

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

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

相关推荐

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

SQL实战宝典:快速上手数据库查询与优化

文章目录 SQL 速成手册SQL 的主要功能1、基本查询语句2、表操作语句3、数据操作语句4、函数与聚合操作5、子查询与联接6、高级操作7、性能优化与安全性 基本查询语句表操作语句数据操作语句函数与聚合操作子查询与联接高级操作性能优化与安全性 SQL 速成手册 SQL&#xff08;S…

DataX 本地调试配置

简要说明 根据自己的开发需求&#xff0c;完成了reader、writer、transformer开发后&#xff0c;在ide内通过Engine入口&#xff0c;调试自己的插件和job的json。 前置条件 已在系统安装了datax&#xff0c;本例子是在windows环境下&#xff0c;安装包地址https://github.co…

204、【动态规划】牛客网 ——DP3 跳台阶扩展问题(Python版本)

题目描述 原题链接&#xff1a;DP3 跳台阶扩展问题 解题思路 一个DP问题&#xff0c;相比于普通爬楼&#xff08;只能爬一层或者两层&#xff09;对应的状态函数为 d p [ i ] d p [ i − 1 ] d p [ i − 2 ] dp[i] dp[i - 1] dp[i - 2] dp[i]dp[i−1]dp[i−2]。本题的dp…

什么是倾斜45度的火山图?

一位老师聊起火山图&#xff08;Volcano plot | 别再问我这为什么是火山图 &#xff08;在线轻松绘制&#xff09;&#xff09;&#xff0c;说见过倾斜45度的类似图&#xff0c;可否演示怎么画&#xff1f;想了下&#xff0c;可能是下面这种图&#xff0c;绘起来看看。 检查和安…

零代码GIS场景视效升级:支持TMS/WMS/WMTS协议

首先和大家聊聊为什么现在很多人都在追求GIS场景的视效提升。第一是因为GIS场景本身需要包含多种自然信息&#xff0c;越是优秀的视觉效果&#xff0c;就越能直观反应出真实的地理信息&#xff0c;增强系统的实用性&#xff1b;第二则是因为能够极大降低系统的使用门槛&#xf…

MinIO使用基础教程

MinIO使用基础教程 一、背景二、快速安装2.1 虚拟机安装2.2 Windows安装2.2.1 下载MinIO服务器2.2.2 启动 MinIO Server2.2.3 通过浏览器访问MinIO服务控制台 三、使用介绍3.1 创建存储桶3.2 上传和下载文件3.3 设置文件公开访问 四、实战SpringBoot Minio实现文件上传和查询五…

2024春秋杯网络安全联赛夏季赛Crypto(AK)解题思路及用到的软件

2024春秋杯网络安全联赛夏季赛Crypto(AK) 2024春秋杯网络安全联赛夏季赛Crypto解题思路以及用到的软件 所有题用到的软件 1.vm(虚拟机kali)和Ubuntu&#xff0c;正常配置即可B站有很多。 2.Visual Studio Code(里面要配置python&#xff0c;crypto库和Sagemath数学软件系统S…

uni-app框架+vue 实现上拉加载和下拉刷新功能

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;我是码喽的自我修养&#xff01;今天给大家分享uni-app框架vue实现上拉加载和下拉刷新功能&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到带大家&#xff0…

1. kubernetes核心组件

kubernetes核心组件 一、kubernetes概述1、kubernetes是什么2、kubernetes作用/优势 二、kubernetes核心组件1、节点类型2、核心组件2.1 Master节点的组件2.2 Node节点的组件 3、k8s创建容器的流程 一、kubernetes概述 1、kubernetes是什么 由google公司基于go语言开发的集群…

YOLOv8预测时报错ValueError

【问题描述】执行YOLOv8预测代码时&#xff1a; # 导入训练好的权重文件做预测 from ultralytics import YOLO# Load a pretrained YOLOv8n model model YOLO("/data/yolov8/runs/detect/train6/weights/best.pt")# Run inference on bus.jpg with arguments model…

拆分盘理财模式:深度剖析与理性投资

一、新型理财视角&#xff1a;拆分盘的重新定义 拆分盘&#xff0c;这一投资概念常被包装为“稳健增长”的代名词&#xff0c;尤其在网络金融领域。它本质上并非传统股市中的股票&#xff0c;而是一种基于会员增长与资金流动的理财机制。其核心在于&#xff0c;通过不断吸纳新…

java算法day20

java算法day20 701.二叉搜索树中的插入操作450.删除二叉搜索树中的节点108 将有序数组转换为二叉搜索树 本次的题目都是用递归函数的返回值来完成&#xff0c;多熟悉这样的用法&#xff0c;很方便。 其实我感觉&#xff0c;涉及构造二叉树的题目&#xff0c;用递归函数的返回值…

2024 年 100 大数据科学面试问答

2024 年 100 大数据科学面试问答 一、说明 数据科学是一个快速发展的领域&#xff0c;它正在改变组织根据数据理解和做出决策的方式。因此&#xff0c;公司越来越多地寻求聘请数据科学家来帮助他们理解数据并推动业务成果。这导致了对数据科学家的高需求&#xff0c;这些职位的…

TikTok矩阵:从0到百万粉丝的秘密!

在TikTok这个充满活力与创意的短视频平台上&#xff0c;每一位创作者都怀揣着成为耀眼明星的梦想。如何让自己的作品脱颖而出&#xff0c;吸引并留住万千粉丝的目光&#xff0c;成为了每一位创作者亟待解决的问题。此时&#xff0c;TikTok矩阵策略便如同一盏明灯&#xff0c;照…

【BES2500x系列 -- RTX5操作系统】系统启动流程 -- boot loader概念讲解 --(九)

&#x1f48c; 所属专栏&#xff1a;【BES2500x系列】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f49…

力扣高频SQL 50题(基础版)第七题

文章目录 力扣高频SQL 50题&#xff08;基础版&#xff09;第七题1068. 产品销售分析 I题目说明思路分析实现过程准备数据&#xff1a;实现方式&#xff1a;结果截图:总结&#xff1a; 力扣高频SQL 50题&#xff08;基础版&#xff09;第七题 1068. 产品销售分析 I 题目说明 …

mysql + Oracle

eg627. 变更性别 Salary 表&#xff1a; ----------------------- | Column Name | Type | ----------------------- | id | int | | name | varchar | | sex | ENUM | | salary | int | ----------------------- id 是这个表…

eclipse 没有war file 选项 不能导入和导出war包

1 eclipse打包war,项目右键 2 安装Web和Java EE插件, 在Eclipse中选择Help菜单&#xff0c;然后选择Install New Software。在Work with下拉菜单中选择All Available Sites&#xff0c;然后选择Web, XML, Java EE and OSGi Enterprise Development进行安装。完成安装后&#xf…

海康视频WEB插件

引入相关依赖 index.html <script src"/video/web-control_1.2.5.min.js"></script> <script src"/video/jquery-1.12.4.min.js" type"text/javascript"></script> <script src"/video/jsencrypt.min.js" …

使用LSTM完成时间序列预测

c 在本教程中&#xff0c;我们将介绍一个简单的示例&#xff0c;旨在帮助初学者入门时间序列预测和 PyTorch 的使用。通过这个示例&#xff0c;你可以学习如何使用 LSTMCell 单元来处理时间序列数据。 我们将使用两个 LSTMCell 单元来学习从不同相位开始的正弦波信号。模型在…