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

这篇具有很好参考价值的文章主要介绍了【动态规划】【中位数】【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;
};
【动态规划】【中位数】【C++算法】1478. 安排邮筒,# 算法题,算法,动态规划,c++,LeetCode,中位数,邮筒,排序

扩展阅读

视频课程

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

【动态规划】【中位数】【C++算法】1478. 安排邮筒,# 算法题,算法,动态规划,c++,LeetCode,中位数,邮筒,排序文章来源地址https://www.toymoban.com/news/detail-832809.html

到了这里,关于【动态规划】【中位数】【C++算法】1478. 安排邮筒的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++编程计算平均数、众数和中位数,可以快速解决计算问题

    说明 求N个整数的平均数,众数和中位数。 小知识: 众数 如有9个数:17 13 17 9 17 17 3 16 17 17出现的次数最多,即为这组数的众数。 此题保证众数是唯一的。 中位数 如有9个数:102 170 96 90 97 106 110 182 100 将这9个数按一定的顺序(从大到小或从小到大)排列后得到: 182 170 110

    2024年02月07日
    浏览(62)
  • 华为OD机试 - 查找众数及中位数(Java & JS & Python & C & C++)

    哈喽,本题库完全免费,收费是为了防止被爬,大家订阅专栏后可以私信联系退款。感谢支持 众数是指一组数据中出现次数量多的那个数,众数可以是多个。 中位数是指把一组数据从小到大排列,最中间的那个数,如果这组数据的个数是奇数,那最中间那个就是中位数,如

    2024年04月08日
    浏览(36)
  • 【华为OD机考 统一考试机试C卷】 查找众数及中位数(C++ Java JavaScript Python)

    目前在考C卷,经过两个月的收集整理, C卷真题已基本整理完毕 抽到原题的概率为2/3到3/3, 也就是最少抽到两道原题。 请注意:大家刷完C卷真题,最好要把B卷的真题刷一下,因为C卷的部分真题来自B卷。 另外订阅专栏还可以联系笔者开通在线OJ进行刷题,提高刷题效率。

    2024年02月04日
    浏览(39)
  • 19种工程问题,智能优化算法常用指标一键导出为EXCEL,最优值,平均值,标准差,最差值,中位数,秩和检验,箱线图...

    常见的智能算法对比方法除了使用经典的CEC函数外, 工程优化问题 也是比较常用的方法。 本期实现在19种工程优化问题上对智能算法的指标进行一键统计! 使你的论文更具说服力! 19种工程优化问题包含如下: 关于上述工程问题的相关介绍,网络上有很多,这里就不再详细

    2024年04月11日
    浏览(83)
  • 【每日一题】中位数

    一个长度为 L ( L ≥ 1 ) 的升序序列 S,处在第 [L / 2] 个位置的数称为 S 的中位数。 例如,若序列 S1 = (11, 13, 15, 17, 19),则 S1 的中位数是 15 。 两个序列的中位数 是含它们所有元素的升序序列的中位数。例如,若 S2 = (2, 4, 6, 8, 20),则 S1 和 S2 的中位数是 11 。 给出两个有序序列

    2024年02月04日
    浏览(33)
  • 【LeetCode: 295. 数据流的中位数 + 堆】

    🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,CSDN-Java领域优质创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文

    2024年02月19日
    浏览(29)
  • 4. 寻找两个正序数组的中位数

    给定两个大小分别为  m  和  n  的正序(从小到大)数组  nums1  和  nums2 。请你找出并返回这两个正序数组的  中位数  。 算法的时间复杂度应该为  O(log (m+n))  。 示例 1: 示例 2: 提示: nums1.length == m nums2.length == n 0 = m = 1000 0 = n = 1000 1 = m + n = 2000 -106 = nums1[i], nums2[i]

    2024年01月18日
    浏览(28)
  • 中位数绝对偏差(MAD)法处理离群值

    作者:非妃是公主 专栏:《数学建模》 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 中位数绝对偏差(MAD)是由Hampel(1974)发现并推广的,中位数(M)和平均数(mean)一样,是中心趋势的衡量标准,但它的优点是对异常值的存在非常不敏感。异常检测

    2024年02月08日
    浏览(29)
  • MATLAB知识点:median :计算中位数

    ​讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 节选自第3章 3.4.1节 中位数又称中值,我们将数据按从小到大的顺序排列,在排列后的数据中居于中间位置的

    2024年04月11日
    浏览(32)
  • 4---寻找两个正序数组的中位数

    给定两个大小分别为 m m m 和 n n n 的正序(从小到大)数组 n u m s 1 nums1 n u m s 1 和 n u m s 2 nums2 n u m s 2 。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O ( l o g ( m + n ) ) O(log (m+n)) O ( l o g ( m + n )) 。 示例 1: 输入 :nums1 = [1,3], nums2 = [2] 输出 :2.00000 解释

    2024年02月03日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包