【动态规划】【中位数】【C++算法】1478. 安排邮筒

# 作者推荐

【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目

本文涉及知识点

动态规划汇总

LeetCode1478. 安排邮筒

给你一个房屋数组houses 和一个整数 k ,其中 houses[i] 是第 i 栋房子在一条街上的位置,现需要在这条街上安排 k 个邮筒。
请你返回每栋房子与离它最近的邮筒之间的距离的 最小 总和。
答案保证在 32 位有符号整数范围以内。
示例 1:
输入:houses = [1,4,8,10,20], k = 3
输出:5
解释:将邮筒分别安放在位置 3, 9 和 20 处。
每个房子到最近邮筒的距离和为 |3-1| + |4-3| + |9-8| + |10-9| + |20-20| = 5 。
示例 2:
输入:houses = [2,3,5,12,18], k = 2
输出:9
解释:将邮筒分别安放在位置 3 和 14 处。
每个房子到最近邮筒距离和为 |2-3| + |3-3| + |5-3| + |12-14| + |18-14| = 9 。
示例 3:
输入:houses = [7,4,6,1], k = 1
输出:8
示例 4:
输入:houses = [3,6,14,10], k = 4
输出:0
提示:
n == houses.length
1 <= n <= 100
1 <= houses[i] <= 104
1 <= k <= n
数组 houses 中的整数互不相同。

动态规划

原理

houser[i,j]之间安装邮筒,安装到正中间的房子是最优解。
a,假定房子数是奇数,假定共有2n+1个房子。假定左边有i1个房子,右边有i2个房子。如果i1 < i2,则右移可以缩短距离;i1 > i2,则左移可以缩短距离。如果邮筒不在屋子上,则i1永远不会等于i2。i1==i2,则必定在最中间的屋子。i+(j-i)/2。
b,屋子为偶数,在中间的两坐房子之间,才会让i1和i2。其实中间两间房子的任何一间房子都可以。
可以统一为:i+(j-i)/2
确切的说 { 左边及本身的房子数小于右边的房子数,右移动。 右边及本身的房子数小于左边的房子数,左移动。 \begin{cases} 左边及本身的房子数小于右边的房子数,右移动。\\ 右边及本身的房子数小于左边的房子数,左移动。\\ \end{cases} {左边及本身的房子数小于右边的房子数,右移动。右边及本身的房子数小于左边的房子数,左移动。 → \rightarrow 稳定状态下,必须
{ i 1 > = i 2 , i 1 < = i 2 → i 1 = = i 2 邮筒不在房子上 i 1 + 1 > = i 2 , i 2 + 1 > = i 1 → a b s ( i 1 − i 2 ) < = 1 邮筒在房子上 → \begin{cases} i1 >=i2,i1 <=i2 \rightarrow i1==i2 & 邮筒不在房子上 \\ i1+1>=i2,i2+1 >= i1 \rightarrow abs(i1-i2)<=1 & 邮筒在房子上\\ \end{cases} \rightarrow {i1>=i2,i1<=i2i1==i2i1+1>=i2,i2+1>=i1abs(i1i2)<=1邮筒不在房子上邮筒在房子上
如果房子数量是奇数
{ 邮筒不在房子上 i 1 = = i 2 → ( i 1 + i 2 ) 是偶数 → 房子总数是奇数矛盾 邮筒在房子上且 i 1 等于 i 2 正中间的房子 邮筒在房子上且 i 1 和 i 2 相差 1 假定 11 + 1 = i 2 → i 1 + i 2 + 1 是偶数,和总数是奇数矛盾 → \begin{cases} 邮筒不在房子上& i1==i2 \rightarrow (i1+i2)是偶数 \rightarrow 房子总数是奇数矛盾 \\ 邮筒在房子上且i1等于i2 & 正中间的房子 \\ 邮筒在房子上且i1和i2相差1 & 假定11+1=i2 \rightarrow i1+i2+1是偶数,和总数是奇数矛盾 \\ \end{cases} \rightarrow 邮筒不在房子上邮筒在房子上且i1等于i2邮筒在房子上且i1i2相差1i1==i2(i1+i2)是偶数房子总数是奇数矛盾正中间的房子假定11+1=i2i1+i2+1是偶数,和总数是奇数矛盾 如果房子的数量是奇数则只能安装在最中间。
如果房子数量是偶数
{ 邮筒不在房子上 i 1 = = i 2 → 中间两间房子的空地 邮筒在房子上且 i 1 等于 i 2 i 1 + i 2 + 1 是奇数,与假设矛盾 邮筒在房子上且 i 1 和 i 2 相差 1 中间任意两间房子 → \begin{cases} 邮筒不在房子上& i1==i2 \rightarrow 中间两间房子的空地 \\ 邮筒在房子上且i1等于i2 & i1+i2+1是奇数,与假设矛盾 \\ 邮筒在房子上且i1和i2相差1 & 中间任意两间房子 \\ \end{cases} \rightarrow 邮筒不在房子上邮筒在房子上且i1等于i2邮筒在房子上且i1i2相差1i1==i2中间两间房子的空地i1+i2+1是奇数,与假设矛盾中间任意两间房子
如果房间数是偶数,则中间的两间房子及之间的空地都是最优解。

预处理

vDis[i][j] ,记录一个邮筒到house[i,j]的距离之和。houses要先排序。

动态规划的状态表示

dp[i][j] 表示 j个邮筒支持前i栋房最小距离。

动态规划的状态方程

通过前者状态更新后置状态。
k = 1 i + k < = h o u s e s . l e n g t h \Large_{k=1}^{i+k <= houses.length} k=1i+k<=houses.length pre[i+k][j+1] = min( ⋯ \cdots ,pre[i][j]+vDis[ ⋯ \cdots ])

动态规划的初始值

dp[0][0]=0 ,其它INT_MAX,表示非法值。

动态规划的填表顺序

i从小到大,j从小到大。

动态规划的返回值

dp.back()[k]

代码

核心代码

class Solution {
public:
	int minDistance(vector<int>& houses, int K) {
		m_c = houses.size();
		sort(houses.begin(), houses.end());
		vector<vector<int>> vDis(m_c, vector<int>(m_c));
		for (int center = 0; center < m_c; center++)
		{
			{
				int iDis = 0;
				for (int i = center, j = center; (i >= 0) && (j < m_c); i--, j++)
				{
					iDis += houses[j] - houses[i];
					vDis[i][j] = iDis;
				}
			}
			{
				int iDis = 0;
				for (int i = center, j = center + 1; (i >= 0) && (j < m_c); i--, j++)
				{
					iDis += houses[j] - houses[i];
					vDis[i][j] = iDis;
				}
			}
		}
		vector<vector<int>> dp(m_c + 1, vector<int>(K + 1, INT_MAX));
		dp[0][0] = 0;
		for (int i = 0; i <= m_c; i++)
		{
			for (int j = 0; j < K; j++)
			{
				if (INT_MAX == dp[i][j])
				{
					continue;
				}
				for (int m = 1; m + i <= m_c; m++)
				{
					dp[m + i][j + 1] = min(dp[m + i][j + 1],dp[i][j]+vDis[i][i+m-1]);
				}
			}
		}
		return dp.back().back();
	}
	int m_c;
};

测试用例

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> houses;
	int k;
	{
		Solution sln;
		houses = { 7,4,6,1 };
		k = 1;
		auto res = sln.minDistance(houses, k);
		Assert(8, res);
	}
	{
		Solution sln;
		houses = { 1, 4, 8, 10, 20 };
		k = 3;
		auto res = sln.minDistance(houses, k);
		Assert(5, res);
	}
	{
		Solution sln;
		houses = { 2,3,5,12,18 };
		k = 2;
		auto res = sln.minDistance(houses, k);
		Assert(9, res);
	}
	
	{
		Solution sln;
		houses = { 3,6,14,10 };
		k = 4;
		auto res = sln.minDistance(houses, k);
		Assert(0, res);
	}
}

2023年2月版

class Solution {
public:
int minDistance(vector& houses, int k) {
const int iNotMay = 1000 * 1000 * 10;
std::sort(houses.begin(), houses.end());
m_c = houses.size();
vector pre(m_c);
for (int i = 0; i < m_c; i++)
{
pre[i] = Cost(houses, 0, i + 1);
}
for (int iK = 2; iK <= k; iK++)
{
vector dp(m_c, iNotMay);
for (int iHouse = 0; iHouse < houses.size(); iHouse++)
{
for (int pr = 0; pr < iHouse; pr++)
{
if (iNotMay == pre[pr])
{
continue;
}
dp[iHouse] = min(dp[iHouse], pre[pr] + Cost(houses, pr+1, iHouse + 1));
}
}
pre.swap(dp);
}
return pre.back();
}
int Cost(const vector& houses,int left, int r)
{
int iCost = 0;
int iMean = houses[left + (r - left) / 2];
for (int i = left; i < r; i++)
{
iCost += abs(houses[i] - iMean);
}
return iCost;
}
int m_c;
};

2023年7月版

class Solution {
public:
int minDistance(vector& houses, int k) {
m_c = houses.size();
sort(houses.begin(), houses.end());
vector<vector> vCost(m_c, vector(m_c));
for(int i= 0 ;i < m_c; i++ )
for (int j = i+1; j < m_c; j++)
{
int iMidValue = houses[i] + (houses[j] - houses[i]) / 2;
int cost = 0;
int k = i+1;
for (; houses[k] <= iMidValue; k++)
{
cost += houses[k] - houses[i];
}
for (; k < j; k++)
{
cost += houses[j] - houses[k];
}
vCost[i][j] = cost;
}
const int iNotMay = 1000 * 1000 * 10;
vector<vector> dp(m_c + 1, vector(k + 1, iNotMay));
dp[0][0] = 0;
dp[0][1] = 0;
vector vBegin(m_c);
{
int iSum = 0;
for (int i = 1; i < m_c; i++)
{
iSum += (houses[i] - houses[i - 1]) * i;
vBegin[i] = iSum;
}
}
for (int i = 1; i < m_c; i++)
{
for (int prePos = 0; prePos < i; prePos++)
{
for (int preK = 0; preK < k; preK++)
{
if (iNotMay == dp[prePos][preK])
{
continue;
}
if (0 == preK)
{
dp[i][preK + 1] = vBegin[i];
continue;
}
dp[i][preK + 1] = min(dp[i][preK + 1],dp[prePos][preK] + vCost[prePos][i]);
}
}
}
vector vEnd(m_c);
{
int iSum = 0;
for (int i = m_c - 2; i >= 0; i–)
{
iSum += (houses[i + 1] - houses[i]) * (m_c - 1 - i);
vEnd[i] = iSum;
}
}
int iRet = iNotMay;
for (int i = k-1; i < m_c; i++)
{
iRet = min(iRet, dp[i][k] +vEnd[i]);
}
return iRet;
}
int m_c;
};

扩展阅读

视频课程

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++基础入门:掌握核心概念(超全!)

C作为一门广泛使用的编程语言&#xff0c;以其高性能和灵活性在软件开发领域占据重要地位。无论是游戏开发、系统编程还是实时应用&#xff0c;C都是一个不可或缺的工具。本博客旨在为初学者提供C编程语言的核心概念&#xff0c;帮助你建立坚实的基础。 C关键字 C关键字是编程…

扫拖一体洗地机哪个好用?热门扫拖一体机品牌

扫拖一体洗地机是一种现代化的清洁设备&#xff0c;它可以帮助我们更快、更有效地清洁地面。这几年市面上的主流品牌纷纷更新迭代产品&#xff0c;那么&#xff0c;选择什么品牌的洗地机才是算是一个不错的选择呢&#xff1f;我们先了解下洗地机吧。 洗地机的功能与原理 市面…

编码、理解和实现LLM中的自注意力、多头注意力、交叉注意力和因果注意力

原文链接&#xff1a;understanding-and-coding-self-attention 2024年1月14日 自注意力是 LLM 的一大核心组件。对大模型及相关应用开发者来说&#xff0c;理解自注意力非常重要。近日&#xff0c;Ahead of AI 杂志运营者、机器学习和 AI 研究者 Sebastian Raschka 发布了一篇…

三天翻倍!ARM 被炒成“英伟达第二”?

周一&#xff0c;Arm股价再度大涨29%&#xff0c;盘中涨幅一度超过40%&#xff0c;单日交易量是过去三个月日均交易量的十倍以上&#xff0c;创下历史新高。自2月7日市场收盘后Arm公布财报以来&#xff0c;短短三个交易日内&#xff0c;Arm股价累计上涨超过90%。 上周&#xf…

前端JavaScript篇之await 在等待什么呢?async/await 如何捕获异常

目录 await 在等待什么呢&#xff1f;async/await 如何捕获异常 await 在等待什么呢&#xff1f; await 关键字实际上是等待一个表达式的结果&#xff0c;这个表达式的计算结果可以是 Promise 对象或者其他值。如果 await 后面的表达式不是 Promise 对象&#xff0c;那么 awai…

论文阅读-Pegasus:通过网络内一致性目录容忍分布式存储中的偏斜工作负载

论文名称&#xff1a;Pegasus: Tolerating Skewed Workloads in Distributed Storage with In-Network Coherence Directories 摘要 高性能分布式存储系统面临着由于偏斜和动态工作负载引起的负载不平衡的挑战。本文介绍了Pegasus&#xff0c;这是一个利用新一代可编程交换机…

CTFshow web(php命令执行 68-71)

web68 还是那句话&#xff0c;没看到flag在哪&#xff0c;那就优先找到flag位置 这里cvar_dump(scandir("/")); 直接输出根目录的位置&#xff0c;然后查看源代码&#xff0c;发现flag位置为flag.txt 知道flag在根目录下面的flag.txt直接访问就好了 cinclude(/flag…

【开源】JAVA+Vue.js实现农村物流配送系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2.1 快递信息管理&#xff1a;2.2.2 位置信息管理&#xff1a;2.2.3 配送人员分配&#xff1a;2.2.4 路线规划&#xff1a;2.2.5 个人中心&#xff1a;2.2.6 退换快递处理&#xff1a;…

Zig、C、Rust的Pk1

Zig、C、Rust的Pk1 github.com上看到“A basic comparitive analysis of C, C, Rust, and Zig.”&#xff1a;https://github.com/CoalNova/BasicCompare/tree/main 里边的代码是9个月之前的&#xff0c;用现在的zig 0.11.0 及0.12-dev都无法通过编译(具体为&#xff1a;zig-w…

快速搭建PyTorch环境:Miniconda一步到位

快速搭建PyTorch环境&#xff1a;Miniconda一步到位 &#x1f335;文章目录&#x1f335; &#x1f333;一、为何选择Miniconda搭建PyTorch环境&#xff1f;&#x1f333;&#x1f333;二、Miniconda安装指南&#xff1a;轻松上手&#x1f333;&#x1f333;三、PyTorch与Minic…

langchain==win11搭建使用GPU

annaconda安装Python 3.11.7 下载代码&#xff1a; GitHub - chatchat-space/Langchain-Chatchat: Langchain-Chatchat&#xff08;原Langchain-ChatGLM&#xff09;基于 Langchain 与 ChatGLM 等语言模型的本地知识库问答 | Langchain-Chatchat (formerly langchain-ChatGLM)…

适用于Android 的 7 大短信恢复应用程序

对于 Android 用户来说&#xff0c;丢失重要的短信可能是一种令人沮丧的体验。幸运的是&#xff0c;有许多短信恢复应用程序可以帮助恢复丢失或删除的短信。在本文中&#xff0c;将与您分享 7 个最佳短信恢复应用程序&#xff0c;并帮助您找到可用于恢复已删除消息的最佳应用程…

医院排队叫号系统的设计与实践

随着医疗服务需求的增加&#xff0c;医院排队叫号系统成为了现代医院管理的必备工具。它不仅可以提高医院服务效率&#xff0c;减少患者等待时间&#xff0c;还可以优化医院资源利用&#xff0c;提升患者就诊体验。本文将介绍医院排队叫号系统的设计与实践&#xff0c;包括系统…

2.13学习总结

1.出差&#xff08;Bleeman—ford&#xff09;&#xff08;spfa&#xff09; &#xff08;dijkstra&#xff09; 2.最小生成树&#xff08;prim&#xff09;&#xff08;Kruskal&#xff09; 最短路问题&#xff1a; 出差https://www.luogu.com.cn/problem/P8802 题目描述 AA …

MySQL:常用指令

MySQL官网 一、在Windows 系统 cmd窗口里执行的命令 启动:net start MySQL停止:net stop MySQL卸载:sc delete MySQL 二、在macOS系统终端里执行的命令 启动&#xff1a;mysql.server start停止&#xff1a;mysql.server stop重启&#xff1a;mysql.server restart 三、执行帮…

多尺度神经网络新一代创新!精度与速度完美平衡,实现多领域应用落地

多尺度神经网络的设计通常基于对频率原则的理解&#xff0c;目的是为了解决高频成分学习慢的问题。这些网络通过特殊设计&#xff0c;比如给高频成分加更多的权重或者将高频成分平移到低频&#xff0c;来提高学习效率。 为了满足在不同层次上理解和处理数据的需求&#xff0c;…

JS游戏项目合集【附源码】

文章目录 一&#xff1a;迷宫小游戏二&#xff1a;俄罗斯方块三&#xff1a;压扁小鸟 一&#xff1a;迷宫小游戏 【迷宫游戏】是一款基于HTML5技术开发的游戏&#xff0c;玩法简单。玩家需要在一个迷宫中找到出口并成功逃脱&#xff0c;本项目还有自动寻路&#xff08;Track&a…

【开源】JAVA+Vue.js实现城市桥梁道路管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥梁4.2 新增城市桥梁4.3 编辑城市桥梁4.4 删除城市桥梁4.5 查询单个城市桥梁 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的城市桥梁道路管理系统&#xff0c;支持…

Netty应用(九) 之 编解码器概念 Netty常见的编解码器

目录 22.编解码器 22.1 编解码的概念 22.2 netty中的编解码 22.3 序列化 23.编解码器在使用过程中的两部分核心内容 23.1 序列化协议&#xff08;编码格式&#xff09;&#xff08;传输数据的格式&#xff09; 23.1.1 Java默认的序列化与反序列化 23.1.2 XML的序列化与反…

比特币突破5万美元,2年来首次

作者&#xff1a;秦晋 2月13日凌晨&#xff0c;时隔两年&#xff0c;比特币首次突破50000美元关口。最高触及50363美元、24小时涨幅3.53%。创下2021年12月以来的新高。 据《财富》报道&#xff0c;本次上涨得益于三方面&#xff0c;首先是比特币ETF资金流入&#xff0c;比特币E…
最新文章