【键值皆有序map 线段树 数学 】100240. 最小化曼哈顿距离

news2024/11/28 16:49:38

本文涉及知识点

键值皆有序map 线段树 数学

LeetCode100240. 最小化曼哈顿距离

给你一个下标从 0 开始的数组 points ,它表示二维平面上一些点的整数坐标,其中 points[i] = [xi, yi] 。
两点之间的距离定义为它们的曼哈顿距离。
请你恰好移除一个点,返回移除后任意两点之间的 最大 距离可能的 最小 值。
示例 1:
输入:points = [[3,10],[5,15],[10,2],[4,4]]
输出:12
解释:移除每个点后的最大距离如下所示:

  • 移除第 0 个点后,最大距离在点 (5, 15) 和 (10, 2) 之间,为 |5 - 10| + |15 - 2| = 18 。
  • 移除第 1 个点后,最大距离在点 (3, 10) 和 (10, 2) 之间,为 |3 - 10| + |10 - 2| = 15 。
  • 移除第 2 个点后,最大距离在点 (5, 15) 和 (4, 4) 之间,为 |5 - 4| + |15 - 4| = 12 。
  • 移除第 3 个点后,最大距离在点 (5, 15) 和 (10, 2) 之间的,为 |5 - 10| + |15 - 2| = 18 。
    在恰好移除一个点后,任意两点之间的最大距离可能的最小值是 12 。
    示例 2:
    输入:points = [[1,1],[1,1],[1,1]]
    输出:0
    解释:移除任一点后,任意两点之间的最大距离都是 0 。

提示:
3 <= points.length <= 105
points[i].length == 2
1 <= points[i][0], points[i][1] <= 108

数学

假定p1到p2的距离最大,则如果不删除p1或p2,最大距离一定不会变小。
我们只需要找到任意一对p1、p2,分别尝试删除p1和p2的最大距离。问题就转化成求:最大曼哈顿距离。
最大曼哈顿距离,应该有公式和模板。但我没有。这两天在研究线段树,就用线段树。结果11:59才完成编码。赛下,调试了一个小时才搞定。

线段树

将points 按x排序,i表示第一个点,j表示第二个点。则xi <= xj恒成立。只需要考虑yi和yj的大小。
{ x j − x i + y j − y i = ( x j + y j ) − ( x i + y i ) y i < = y j x j − x i + y i − y j = ( x j − y j ) − ( x i − y i ) y i > = y j \begin{cases} xj-xi+yj-yi = (xj+yj)-(xi+yi) && yi <= yj \\ xj-xi+yi-yj = (xj-yj)-(xi-yi) && yi >= yj \\ \end{cases} {xjxi+yjyi=(xj+yj)(xi+yi)xjxi+yiyj=(xjyj)(xiyi)yi<=yjyi>=yj
我们只需要计算 (xi+yi)和(xi-yi) 的最小值。用两棵最小树,分别记录最小值,单点更新,区间查找。难点:先要离散化,否则空间复杂度会超。

键值皆有序映射

情况一: yi <= yj
(xi+yi)和yj都越小越好,故键yj 升序,值(xi+yi)降序,如果冲突,淘汰键大的。
情况二:yi >= yj
(xi- yi) 越小越好,yj越大越好。故键yj升序,值(xi- yi)升序。发生冲突,淘汰键小的。

我看题解才知道的

切比雪夫距离(Chebyshev Distance) 在二维空间中,切比雪夫距离是通过计算两个点在各个坐标轴上的差值的绝对值中的最大值来衡量它。
曼哈顿距离在坐标轴旋转 45 度后与切比雪夫距离等价。

代码

线段树实现

class CDiscretize //离散化
{
public:
	CDiscretize(vector<int> nums)
	{
		sort(nums.begin(), nums.end());
		nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
		m_nums = nums;
		for (int i = 0; i < nums.size(); i++)
		{
			m_mValueToIndex[nums[i]] = i;
		}
	}
	int operator[](const int value)const
	{
		auto it = m_mValueToIndex.find(value);
		if (m_mValueToIndex.end() == it)
		{
			return -1;
		}
		return it->second;
	}
	int size()const
	{
		return m_mValueToIndex.size();
	}
	vector<int> m_nums;
protected:	
	unordered_map<int, int> m_mValueToIndex;
};

template<class TSave, class TRecord>
class CSingUpdateLineTree
{
public:
	CSingUpdateLineTree(int iEleSize, TSave tDefautl) :m_iEleSize(iEleSize), m_vSave(iEleSize * 4, tDefautl) {

	}
	void Update(int index, TRecord update) {
		Update(1, 1, m_iEleSize, index + 1, update);
	}
	void Query(int leftIndex, int leftRight) {
		Query(1, 1, m_iEleSize, leftIndex + 1, leftRight + 1);
	}
	void Init() {
		Init(1, 1, m_iEleSize);
	}
	const int m_iEleSize;
protected:
	void Init(int iNodeNO, int iSaveLeft, int iSaveRight)
	{
		if (iSaveLeft == iSaveRight) {
			OnInit(m_vSave[iNodeNO], iSaveLeft);
			return;
		}
		const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
		Init(iNodeNO * 2, iSaveLeft, mid);
		Init(iNodeNO * 2 + 1, mid + 1, iSaveRight);
		OnUpdateParent(m_vSave[iNodeNO], m_vSave[iNodeNO * 2], m_vSave[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
	}
	void Query(int iNodeNO, int iSaveLeft, int iSaveRight, int iQueryLeft, int iQueryRight) {
		if ((iSaveLeft >= iQueryLeft) && (iSaveRight <= iQueryRight)) {
			OnQuery(m_vSave[iNodeNO]);
			return;
		}
		if (iSaveLeft == iSaveRight) {//没有子节点
			return;
		}
		const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
		if (mid >= iQueryLeft) {
			Query(iNodeNO * 2, iSaveLeft, mid, iQueryLeft, iQueryRight);
		}
		if (mid + 1 <= iQueryRight) {
			Query(iNodeNO * 2 + 1, mid + 1, iSaveRight, iQueryLeft, iQueryRight);
		}
	}
	void Update(int iNodeNO, int iSaveLeft, int iSaveRight, int iUpdateNO, TRecord update) {
		if (iSaveLeft == iSaveRight)
		{
			OnUpdate(m_vSave[iNodeNO], iSaveLeft, update);
			return;
		}
		const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;
		if (iUpdateNO <= mid) {
			Update(iNodeNO * 2, iSaveLeft, mid, iUpdateNO, update);
		}
		else {
			Update(iNodeNO * 2 + 1, mid + 1, iSaveRight, iUpdateNO, update);
		}
		OnUpdateParent(m_vSave[iNodeNO], m_vSave[iNodeNO * 2], m_vSave[iNodeNO * 2 + 1], iSaveLeft, iSaveRight);
	}
	virtual void OnInit(TSave& save, int iSave) = 0;
	virtual void OnQuery(TSave& save) = 0;
	virtual void OnUpdate(TSave& save,int iSaveLeft, const TRecord& update) = 0;
	virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) = 0;
	vector<TSave> m_vSave;
};


template<class TSave=pair<int,int>, class TRecord =int>
class CMyLineTree : protected CSingUpdateLineTree<TSave, TRecord>
{
public:
	CMyLineTree(CDiscretize& dis,int iEleSize) : m_dis(dis),CSingUpdateLineTree<TSave, TRecord>(iEleSize,std::make_pair(1e9,-1)) {

	}
	void Update(int y, TRecord update) {
		CSingUpdateLineTree<TSave, TRecord>::Update(m_dis[y],update);
	}
	void QueryLessEqual(int y) {
		m_prMin = { 1e9,-1 };
		CSingUpdateLineTree<TSave, TRecord>::Query(0, m_dis[y]);
	}
	void QueryMoreEqual(int y) {
		m_prMin = { 1e9,-1 };
		CSingUpdateLineTree<TSave, TRecord>::Query(m_dis[y], m_dis.size()-1);
	}
	pair<int, int> m_prMin = { 1e9,-1 };
protected:
	virtual void OnInit(TSave& save, int iSave) override
	{
	}
	virtual void OnQuery(TSave& save) override
	{
		if (save < m_prMin) {
			m_prMin = save;
		}	
	}
	virtual void OnUpdate(TSave& save, int iSaveLeft,const TRecord& update) override
	{
		TSave tmp = { update,m_dis.m_nums[iSaveLeft - 1] };
		save = min(save,tmp);
	}
	virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) override
	{
		par = min(left, r);
	}	
	CDiscretize& m_dis;
}; 
class Solution {
public:
	int minimumDistance(vector<vector<int>>& points) {
		sort(points.begin(), points.end(), [](const auto& v1, const auto& v2) {return v1[0] < v2[0]; });
		auto [tmp, i1, i2] = Max(points);
		auto pts1 = points, pts2 = points;
		pts1.erase(pts1.begin() + i1);
		pts2.erase(pts2.begin() + i2);
		auto [m1, tmp1, tmp2] = Max(pts1);
		auto [m2, tmp3, tmp4] = Max(pts2);
		return min(m1, m2);
	}
	std::tuple<int, int, int> Max(const vector<vector<int>>& pts) {
		vector<int> ys;
		for (const auto& pt : pts) {
			ys.emplace_back(pt[1]);
		}
		CDiscretize dis(ys);
		CMyLineTree mXAndY(dis,dis.size()), mXSubY(dis, dis.size());
		const int n = pts.size();
		int iRet = -1e9,i2;
		std::pair<int, int> xy;
		for (int i = 1; i < n; i++) {
			mXAndY.Update(pts[i - 1][1], pts[i - 1][0] + pts[i - 1][1]);
			mXSubY.Update(pts[i - 1][1], pts[i - 1][0] - pts[i - 1][1]);
			mXAndY.QueryLessEqual(pts[i][1]);
			const int iDis1 = pts[i][0] + pts[i][1] - mXAndY.m_prMin.first;
			if (iDis1 > iRet) {
				iRet = iDis1;
				xy = { mXAndY.m_prMin.first- mXAndY.m_prMin.second, mXAndY.m_prMin.second };
				i2 = i;
			}
			mXSubY.QueryMoreEqual(pts[i][1]);
			const int iDis2 = pts[i][0] - pts[i][1] - mXSubY.m_prMin.first;
			if (iDis2 > iRet) {
				iRet = iDis2;
				xy = { mXSubY.m_prMin.first + mXSubY.m_prMin.second, mXSubY.m_prMin.second };
				i2 = i;
			}
		}
		int i1 = 0;
		for (; (xy.first != pts[i1][0]) || (xy.second != pts[i1][1]);i1++);
		return { iRet,i1,i2 };
	}
};

测试用例

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<vector<int>> points;
	{
		points = { {9,8},{1,8},{3,1},{9,1},{7,7},{3,6} };
		auto res = Solution().minimumDistance(points);
		Assert(13, res);
	}
	{
		points = { {3,10},{5,15},{10,2},{4,4} };
		auto res = Solution().minimumDistance(points);
		Assert(12, res);
	}
	{
		points = { {3,2},{3,9},{7,10},{4,4},{8,10},{2,7} };
		auto res = Solution().minimumDistance(points);
		Assert(10, res);
	}
	
	{
		points = { {1,1},{1,1},{1,1},{1,1} };
		auto res = Solution().minimumDistance(points);
		Assert(0, res);
	}
	
	//CConsole::Out(res);
}

键值皆有需map

template<class _Kty, class _Ty, bool bValueAsc, bool bOutSmallKey>
class COrderValueMap
{
public:
	void Add(_Kty key, _Ty value)
	{
		if (bOutSmallKey)
		{
			if (bValueAsc)
			{
				AddOutSmall(key, value, std::less_equal<_Ty>(), std::greater_equal<_Ty>());
			}
			else
			{
				AddOutSmall(key, value, std::greater_equal<_Ty>(), std::less_equal<_Ty>());
			}
		}
		else
		{
			if (bValueAsc)
			{
				AddNotOutSmall(key, value, std::greater_equal<_Ty>(), std::less_equal<_Ty>());
			}
			else
			{
				AddNotOutSmall(key, value, std::less_equal<_Ty>(), std::greater_equal<_Ty>());
			}
		}
	};
	std::map<_Kty, _Ty> m_map;
protected:
	template<class _Pr1, class _Pr2>
	void AddOutSmall(_Kty key, _Ty value, _Pr1 pr1, _Pr2 pr2)
	{
		auto it = m_map.lower_bound(key);
		if ((m_map.end() != it) && pr1(it->second, value))
		{
			return;//被旧值淘汰
		}
		auto ij = it;
		while (it != m_map.begin())
		{
			--it;
			if (pr2(it->second, value))
			{
				it = m_map.erase(it);
			}
			else
			{
				break;
			}
		}
		m_map[key] = value;
	}
	template<class _Pr1, class _Pr2>
	void AddNotOutSmall(_Kty key, _Ty value, _Pr1 pr1, _Pr2 pr2)
	{
		auto it = m_map.upper_bound(key);
		if ((m_map.begin() != it) && pr1(std::prev(it)->second, value))
		{
			return;//被淘汰
		}
		auto ij = it;
		for (; (m_map.end() != ij) && pr2(ij->second, value); ++ij);
		m_map.erase(it, ij);
		m_map[key] = value;
	};

};


class Solution {
public:
	int minimumDistance(vector<vector<int>>& points) {
		sort(points.begin(), points.end(), [](const auto& v1, const auto& v2) {return v1[0] < v2[0]; });
		auto [tmp, i1, i2] = Max(points);
		auto pts1 = points, pts2 = points;
		pts1.erase(pts1.begin() + i1);
		pts2.erase(pts2.begin() + i2);
		auto [m1, tmp1, tmp2] = Max(pts1);
		auto [m2, tmp3, tmp4] = Max(pts2);
		return min(m1, m2);
	}
	std::tuple<int, int, int> Max(const vector<vector<int>>& pts) {
		COrderValueMap<int, int, false, false> mXAndY;
		COrderValueMap<int, int, true, true> mXSubY;
		const int n = pts.size();
		int iRet = -1e9,i2;
		for (int i = 1; i < n; i++) {
			mXAndY.Add(pts[i - 1][1], pts[i - 1][0] + pts[i - 1][1]);
			mXSubY.Add(pts[i - 1][1], pts[i - 1][0] - pts[i - 1][1]);
			auto it1 = mXAndY.m_map.upper_bound(pts[i][1]);
			if (mXAndY.m_map.begin() != it1 ) {
				--it1;
				const int iDis1 = pts[i][0] + pts[i][1] - it1->second;
				if (iDis1 > iRet) {
					iRet = iDis1;
					i2 = i;
				}
			}
			auto it2 = mXSubY.m_map.lower_bound(pts[i][1]);
			if (it2 != mXSubY.m_map.end()) {
				const int iDis2 = pts[i][0] - pts[i][1] - it2->second;
				if (iDis2 > iRet) {
					iRet = iDis2;
					i2 = i;
				}
			}
		}
		int i1 = -1,iMinDis=-1;
		for (int i = 0; i < n; i++) {
			const int curDis = abs(pts[i][0] - pts[i2][0]) + abs(pts[i][1] - pts[i2][1]);
			if (curDis > iMinDis) {
				iMinDis = curDis;
				i1 = i;
			}
		}
		return { iRet,i1,i2 };
	}
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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/1560408.html

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

相关文章

大数据-TXT文本重复行计数工具

支持系统类型&#xff1a;Windows 64位系统 Linux 64位系统 苹果64位系统 硬盘要求&#xff1a;固态硬盘&#xff08;有效剩余磁盘空间大小最低3倍于大数据文件的大小&#xff09; 内存要求&#xff1a;最低8G&#xff08;例如只有几百G数据&#xff09; 如果处理TB级大数据文…

Matlab中的脚本和函数

Matlab中的脚本和函数 文章目录 Matlab中的脚本和函数脚本创建脚本代码注释函数创建函数局部函数嵌套函数私有函数匿名函数补充知识函数句柄测试环境:Win11 + Matlab R2021a 脚本 ​ Matlab脚本是最简单的程序文件类型。它们可用于自动执行一系列 Matlab 命令,如命令行重复执…

[linux初阶][vim-gcc-gdb] OneCharter: vim编辑器

一.vim编辑器基础 目录 一.vim编辑器基础 ①.vim的语法 ②vim的三种模式 ③三种模式的基本切换 ④各个模式下的一些操作 二.配置vim环境 ①手动配置(不推荐) ②自动配置(推荐) vim是vi的升级版,包含了更加丰富的功能. ①.vim的语法 vim [文件名] ②vim的三种模式 命令…

《权力》为什么只为某些人所拥有 - 三余书屋 3ysw.net

权力&#xff1a;为什么只为某些人所拥有 大家好&#xff0c;今天我们解读的书名是《权力》&#xff0c;副标题是“为什么只为某些人所拥有”。该书深入探讨了职场中的权力议题&#xff0c;强调获得权力是关键的职场技能之一。在激烈的职场竞争中&#xff0c;缺乏这一技能将使…

14 Games101 - 笔记 - 光线追踪(利用包围盒技术加速光线追踪(KD-Tree and BVH)

14 光线追踪&#xff08;利用包围盒技术加速光线追踪&#xff08;KD-Tree and BVH&#xff09; 在上一节中&#xff0c;我们介绍了whited-style光线追踪的原理&#xff0c;以及实现细节。相比与光栅化中所使用的的Blinn-Phong模型&#xff0c;光线追踪显著了提升了图像质量&am…

《极客时间TonyBai go语言第一课》学习笔记

文章目录 前置篇显式组合并发 入门篇Go 包的初始化次序![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/1388d0d1bddd4a37b98eba5fcb41fc4d.png)初始化一个项目 大纲 前置篇 显式 在 C 语言中&#xff0c;下面这段代码可以正常编译并输出正确结果&#xff1a; #i…

C#.net8创建webapi,使用SqlSugar,仓储模式,DTO,服务层,控制层的综合应用(企业级)

本文源码地址: https://download.csdn.net/download/u012563853/89036104 源码中,也有详细的注释说明。 代码总览: 这是一个综合性比较强的文章,需要有一定的基础,没有基础的人,看了后,会全面的了解一下,有基础的人,看了后会加强认识,更加的巩固,直接在项目中去应…

人工智能时代:如何运用Excel函数与公式结合AI应用办公

前言 本文将结合人工智能的概念和Excel的高级功能&#xff0c;通过具体、详细的示例&#xff0c;展示如何利用Excel的函数与公式提升数据处理和分析的效率。博客内容涵盖基础函数的使用、高级公式的构建、以及如何通过编程接口与Excel进行交互&#xff0c;实现自动化和智能化的…

Python爬虫快速上手,知识介绍与实战demo

目录 前言 一、爬虫是什么&#xff1f; 二、爬虫的基本流程&#xff1a; 三、http协议 请求与响应 四、 request 五、 响应Response 六、总结 七、简单实战demo 前言 简单来说互联网是由一个个站点和网络设备组成的大网&#xff0c;我们通过浏览器访问站点&#xff0c;站点把HT…

混合现实(MR)开发工具

混合现实&#xff08;MR&#xff09;开发工具是一系列软件和框架&#xff0c;它们使得开发者能够创建和优化能够在虚拟与现实世界之间无缝交互的应用程序。以下是一些在MR领域内广泛使用的开发工具。 1.Microsoft Mixed Reality Toolkit (MRTK) MRTK是一个跨平台的工具包&…

Yarn与Zookeeper的介绍

Yarn--三大调度策略 FIFO(先进先出): 目前几乎已经没有人使用了. 类似于: 单行道. 好处: 每个计算任务能独享集群100%的资源. 弊端: 不能并行执行, 如果大任务过多, 会导致小任务执行时间过长. Capacity(容量调度): 我们用…

idea Springboot 电影推荐系统LayUI框架开发协同过滤算法web结构java编程计算机网页

一、源码特点 springboot 电影推荐系统是一套完善的完整信息系统&#xff0c;结合mvc框架和LayUI框架完成本系统springboot dao bean 采用协同过滤算法进行推荐 &#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&…

亮数据,可视化数据采集强大利器

前言 随着信息技术的飞速发展&#xff0c;我们已经进入了一个以数据为中心的世纪。在这个时代&#xff0c;数据不仅仅是信息的载体&#xff0c;它已经成为了推动社会进步、创新科技、增强决策和驱动经济增长的关键资源。 在这个数据世纪中&#xff0c;掌握数据的能力等同于掌…

计算机网络—VLAN 间路由配置

目录 1.拓扑图 2.实验环境准备 3.为 R3 配置 IP 地址 4.创建 VLAN 5.配置 R2 上的子接口实现 VLAN 间路由 6.配置文件 1.拓扑图 2.实验环境准备 配置R1、R3和S1的设备名称&#xff0c;并按照拓扑图配置R1的G0/0/1接口的IP地址。 [Huawei]sysname R1 [R1]interface Giga…

希亦、洁盟、大宇超声波清洗机好用吗?比拼谁是性价比之王

在追求高效生活品质的今天&#xff0c;超声波清洗机以其独特的清洁技术和便捷的操作方式&#xff0c;成为了家用和商用清洁领域的新宠。尤其对于眼镜用户而言&#xff0c;一台高效的超声波清洗机不仅能够轻松去除镜片上的污渍和细菌&#xff0c;更能保护镜片不受损伤&#xff0…

提升Web开发安全性:分析JScrambler、JShaman等五款在线JavaScript加密混淆工具

摘要 本篇技术博客将介绍五款常用且好用的在线JavaScript加密混淆工具&#xff0c;包括 jscrambler、JShaman、jsfack、freejsobfuscator 和 jjencode。通过对这些工具的功能及使用方法进行详细解析&#xff0c;帮助开发人员更好地保护和加密其 JavaScript 代码&#xff0c;提…

学浪视频如何下载或者录屏

很多同学购买了学浪视频&#xff0c;可是不知道如何下载下来&#xff0c;用录屏&#xff0c;发现学浪PC学生版客户端有防止录屏&#xff0c;为了解决这个问题&#xff0c;我开发了学浪视频下载的客户端 大家有需要自己取一下&#xff0c;截止到4月1号&#xff0c;最新版本是2.…

《自动机理论、语言和计算导论》阅读笔记:p115-p138

《自动机理论、语言和计算导论》学习第 6 天&#xff0c;p115-p138 总结&#xff0c;总计 24 页。 一、技术总结 1.associativity and comutativity (1)commutativity(交换性): Commutativity is the property of an operator that says we can switch the order of its ope…

【TB作品】MSP430G2553,超声波倒车雷达PCB,单片机,超声波SR04,键盘,oled

题目 硬件&#xff1a;MSP430G2553、 SR04超声波传感器 、3*4键盘、 无源蜂鸣器、oled显示屏 软件 1 、实时显示测量得到的距离 2、按键设置一个报警门限数值&#xff0c;直接输入数值后确认 3、低于报警门限数值就开始报警&#xff0c;而且距离越近蜂鸣器的鸣叫频率越高 程序…

ctf题目

目录 1.文件包含的一道题目&#xff0c;没什么难度&#xff0c; 2.一道sql注入的题目&#xff0c;伪静态 3.限制只能本地访问。 1.文件包含的一道题目&#xff0c;没什么难度&#xff0c; 但是一个点就是它这里去包含的那个文件名就是flag&#xff0c;而不是flag.php也不是f…