C++前缀和算法的应用:装包裹的最小浪费空间 原理源码测试用例

简介: C++前缀和算法的应用:装包裹的最小浪费空间 原理源码测试用例

本文涉及的基础知识点

C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频

题目

给你 n 个包裹,你需要把它们装在箱子里,每个箱子装一个包裹。总共有 m 个供应商提供 不同尺寸 的箱子(每个规格都有无数个箱子)。如果一个包裹的尺寸 小于等于 一个箱子的尺寸,那么这个包裹就可以放入这个箱子之中。

包裹的尺寸用一个整数数组 packages 表示,其中 packages[i] 是第 i 个包裹的尺寸。供应商用二维数组 boxes 表示,其中 boxes[j] 是第 j 个供应商提供的所有箱子尺寸的数组。

你想要选择 一个供应商 并只使用该供应商提供的箱子,使得 总浪费空间最小 。对于每个装了包裹的箱子,我们定义 浪费的 空间等于 箱子的尺寸 - 包裹的尺寸 。总浪费空间 为 所有 箱子中浪费空间的总和。

比方说,如果你想要用尺寸数组为 [4,8] 的箱子装下尺寸为 [2,3,5] 的包裹,你可以将尺寸为 2 和 3 的两个包裹装入两个尺寸为 4 的箱子中,同时把尺寸为 5 的包裹装入尺寸为 8 的箱子中。总浪费空间为 (4-2) + (4-3) + (8-5) = 6 。

请你选择 最优 箱子供应商,使得 总浪费空间最小 。如果 无法 将所有包裹放入箱子中,请你返回 -1 。由于答案可能会 很大 ,请返回它对 109 + 7 取余 的结果。

示例 1:

输入:packages = [2,3,5], boxes = [[4,8],[2,8]]

输出:6

解释:选择第一个供应商最优,用两个尺寸为 4 的箱子和一个尺寸为 8 的箱子。

总浪费空间为 (4-2) + (4-3) + (8-5) = 6 。

示例 2:

输入:packages = [2,3,5], boxes = [[1,4],[2,3],[3,4]]

输出:-1

解释:没有箱子能装下尺寸为 5 的包裹。

示例 3:

输入:packages = [3,5,8,10,11,12], boxes = [[12],[11,9],[10,5,14]]

输出:9

解释:选择第三个供应商最优,用两个尺寸为 5 的箱子,两个尺寸为 10 的箱子和两个尺寸为 14 的箱子。

总浪费空间为 (5-3) + (5-5) + (10-8) + (10-10) + (14-11) + (14-12) = 9 。

参数范围

n == packages.length

m == boxes.length

1 <= n <= 105

1 <= m <= 105

1 <= packages[i] <= 105

1 <= boxes[j].length <= 105

1 <= boxes[j][k] <= 105

sum(boxes[j].length) <= 105

boxes[j] 中的元素 互不相同 。

分析

思路

用v代表某个商人所有的箱子,按升序排序。v[0]尺寸的箱子装所有尺寸小于等于v[0]的包括,就是v[0]箱子的数量等于,尺寸为[0,v[0]]箱子的数量。同理v[1]的数量等于尺寸为(v[0],v[1]]包裹的数量。

注意

如果商人最大号的箱子小于最大号包裹,则不能选择此商人。如果所有商人都不能选择,则返回-1。如果多个箱子大于最大号的包裹,这些箱子中只有第一个有用。

用前缀和计算包裹的数量,小心索引溢出。

变量含义

iMax 最大号包裹尺寸
vSum vSum[i] 等于 空间小于等于i 的包裹数量
llNeed 所有包裹的总空间
cur 当前商人提供的箱子的总空间

代码

核心代码

class Solution {
public:
int minWastedSpace(vector& packages, vector<vector>& boxes) {
int iMax = *std::max_element(packages.begin(), packages.end());
vector vNum(iMax + 1);
long long llNeed = 0;
for (const auto& n : packages)
{
vNum[n]++;
llNeed += n;
}
vector vSum = { 0 };//vSum[i] 等于 空间小于等于i 的包裹数量
for (int i = 1; i <= iMax; i++)
{
vSum.emplace_back(vSum.back() + vNum[i]);
}
long long llHas = LLONG_MAX;
for (auto& v : boxes)
{
sort(v.begin(), v.end());
if (v.back() < iMax)
{
continue;
}
int pre = 0;
long long cur = 0;//当前空间上提供的包裹的总容量
for ( auto& n : v)
{
cur += ((long long)vSum[min(n,iMax)] - vSum[pre]) * n;
pre = n;
if (n >= iMax)
{
break;
}
}
llHas = min(llHas, cur);
}
if (LLONG_MAX == llHas)
{
return -1;
}
const long long llMod = 1e9 + 7;
return (llHas - llNeed) % llMod;
}
};

测试用例

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
assert(v1[i] == v2[i]);
}
}
template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}
int main()
{
Solution slu;
vector packages;
vector<vector>boxes;
int res = 0;
packages = { 3,5,8,10,11,12 };
boxes = { {12},{11,9},{10,5,14} };
res = slu.minWastedSpace(packages, boxes);
Assert(9, res);
packages = { 3, 5, 8, 7, 5, 8, 10, 11, 12 };
boxes = { {12},{11,9},{10,5,14} };
res = slu.minWastedSpace(packages, boxes);
Assert(14, res);
packages = { 2,3,5 };
boxes = { {4,8},{2,8} };
res = slu.minWastedSpace(packages, boxes);
Assert(6, res);
packages = { 2,3,5,8,7,6 };
boxes = { {4,8},{2,8} };
res = slu.minWastedSpace(packages, boxes);
Assert(9, res);
//CConsole::Out(res);

}

2023年3月旧代码

class Solution {
public:
int minWastedSpace(vector& packages, vector<vector>& boxes) {
std::sort(packages.begin(), packages.end());
vector vSums(1);
for (const auto& pack : packages)
{
vSums.emplace_back(pack + vSums.back());
}
std::priority_queue que;
for (auto& v : boxes)
{
std::sort(v.begin(), v.end());
long long llCur = 0;
int iHasDo = 0;
for (int j = 0; j < v.size(); j++)
{
auto iCurDoEnd = std::upper_bound(packages.begin() + iHasDo, packages.end(), v[j]) - packages.begin();
long long llCurBox = (long long)v[j] * (iCurDoEnd - iHasDo) - (vSums[iCurDoEnd] - vSums[iHasDo]);
llCur += llCurBox;
iHasDo = iCurDoEnd;
}
if (packages.size() == iHasDo)
{
que.push(llCur);
if (que.size() > 1)
{
que.pop();
}
}
}
return que.size() ? C1097Int<>(que.top()).ToInt() : -1 ;
}
};

扩展阅读

视频课程

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


相关文章
|
11月前
|
C++
基本二叉树与排序二叉树(C++源码)
本程序实现二叉树基本操作与二叉排序树应用。支持前序建树、四种遍历、求深度、叶子数、第K层节点数及查找功能;并实现二叉排序树的构建、中序输出与查找比较次数统计,分析不同插入顺序对树形态和查找效率的影响。
|
存储 监控 JavaScript
基于布隆过滤器的 Node.js 算法在局域网电脑桌面监控设备快速校验中的应用研究
本文探讨了布隆过滤器在局域网电脑桌面监控中的应用,分析其高效空间利用率、快速查询性能及动态扩容优势,并设计了基于MAC地址的校验模型,提供Node.js实现代码,适用于设备准入控制与重复数据过滤场景。
407 0
|
12月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
602 3
|
12月前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
|
12月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
12月前
|
机器学习/深度学习 算法 安全
小场景大市场:猫狗识别算法在宠物智能设备中的应用
将猫狗识别算法应用于宠物智能设备,是AIoT领域的重要垂直场景。本文从核心技术、应用场景、挑战与趋势四个方面,全面解析这一融合算法、硬件与用户体验的系统工程。
1005 0
|
安全 Java 测试技术
python接口自动化(三)--如何设计接口测试用例(详解)
上篇我们已经介绍了什么是接口测试和接口测试的意义。在开始接口测试之前,我们来想一下,如何进行接口测试的准备工作。或者说,接口测试的流程是什么?有些人就很好奇,接口测试要流程干嘛?不就是拿着接口文档直接利用接口 测试工具测试嘛。其实,如果只是三五个接口,你可以这么做一个临时的接口测试。但是,如果是上百个接口,或者,你们公司的这个项目,第一次做接口测试,那么,我们还是很有必要严格遵守接口测试的流程。
760 0
python接口自动化(三)--如何设计接口测试用例(详解)
|
测试技术
正交试验测试用例设计及工具推荐
在科研和生产实践中,人们往往要做许多次实验来进行某项研究。实验条件一般包括很多因素,当因素的值不同时,实验的结果也不一样。如果想把每个因素的每个值都要实验一遍,总实验数就等于各因素的值的个数的乘积,而这个数往往很大,超过了可接受的成本。 例如,假设某个实验由A,B,C,D四个因素,每个因素都有10个不同的取值,那么如果想把每个因素都考虑到,我们需要做 10*10*10*10=10000次实验。 为了减少实验数目,我们必须选出那些最有代表性的例子。于是,就要用到了正交表法(Orthogonal Array Testing Strategy)。
1222 0
正交试验测试用例设计及工具推荐
|
算法 安全 测试技术
【软件测试】测试用例的设计方法
测试用例写的过于简单,则可能失去了测试用例的意义,设计过于简单的测试用例其实并没有真正的进行设计,只是把需要测试的功能模块记录下来而已,它的作用仅仅是在测试过程中作为一个简单的测试计划,提醒测试人员测试的主要功能包括哪些而已,测试用例设计的本质应该是在设计的过程中理解需求,检验需求,并把对软件系统的测试方法的思路记录下来,以便指导将来的测试
【软件测试】测试用例的设计方法
|
安全 中间件 测试技术
【面试高频】给你一句话需求,让你设计测试用例,该怎么做?
【面试高频】给你一句话需求,让你设计测试用例,该怎么做?
【面试高频】给你一句话需求,让你设计测试用例,该怎么做?

热门文章

最新文章