这段代码是一个解决“在 D 天内送完包裹”问题的算法,通常出现在编程面试或在线编程平台中。目标是找到最小的船只装载能力,使得在给定的天数内能够将所有的包裹运送完成。以下是对代码的逐行详细解释:
函数 check
bool check(vector<int>& weights, int t, int days) {
int n = weights.size();
int cnt = 1; // 记录所需的天数,初始为1,即至少需要一天
int sum = 0; // 当前船只装载重量
for (int i = 0; i < n; i++) {
if (sum + weights[i] > t) { // 如果当前船只不能再装下weights[i]
cnt++; // 增加一天
sum = weights[i]; // 重置当前装载重量为当前包裹的重量
} else {
sum += weights[i]; // 否则继续增加当前包裹的重量
}
}
return cnt <= days; // 检查是否在给定的days内可以送完所有包裹
}
参数:
weights
: 一个整数数组,表示每个包裹的重量。t
: 船只最大承载能力。days
: 要求运送所有包裹所需的最大天数。
逻辑:
- 遍历每个包裹,如果当前累计重量加上新包裹会超过限制,则需要新的运输天数(即换船),并重置累计重量。
- 最后检查实际需要多少天(
cnt
)是否小于等于允许的最大天数(days
)。
函数 shipWithinDays
int shipWithinDays(vector<int>& weights, int days) {
int maxWeight = *max_element(weights.begin(), weights.end()); // 找到最大的单个包裹重量
int totalWeight = accumulate(weights.begin(), weights.end(), 0); // 所有包裹总重
int left = maxWeight, right = totalWeight;
while (left < right) {
int mid = left + (right - left) / 2; // 二分法计算中间值
if (check(weights, mid, days)) {
right = mid; // 如果可以在 'days' 内运输,尝试更小容量
} else {
left = mid + 1; // 否则需要更大的容量
}
}
return right;
}
参数:
weights
: 包裹的重量数组。days
: 要求运输时间。
逻辑:
- 使用二分搜索来确定最小可接受船只容量,从最大的单个包装重量 (
maxWeight
) 开始,到所有包装总重 (totalWeight
) 为止进行搜索。 - 每次迭代都通过调用
check
函数来验证中间值是否满足条件。如果满足条件,就缩小右边界;否则,扩大左边界。
- 使用二分搜索来确定最小可接受船只容量,从最大的单个包装重量 (
总结
这段代码利用二分查找结合贪心策略有效地寻找使得运输能在规定天数内完成的最小船只装载能力。通过适当划分区间,不断优化目标,以达到效率较高、运行时间复杂度为 O(n log m) 的效果,其中 n 是包装数量,m 是总重。
内容由零声教学AI助手提供,问题来源于学员提问