int shipWithinDays(vector<int>& weights, int D) {
int maxW = 0, sumW = 0;
for (int w : weights) {
maxW = max(maxW, w);
sumW += w;
}
int l = maxW, u = sumW;
while (l <= u) {
int m = l + (u - l) / 2;
if (enough(m, weights, D)) {
u = m - 1;
} else {
l = m + 1;
}
}
return l;
}
bool enough(int capacity, vector<int>& weights, int D) {
// 运载力capacity、天数days的关系
int weight = 0, days = 1;
for (int i = 0; i < weights.size(); i++) {
weight += weights[i];
if (weight > capacity) {
days++;
weight = weights[i];
}
}
// capacity越大、days越小、days<=D越返回1
return days <= D;
}
int splitArray(vector<int>& nums, int m) {
// 各子段和的最大值x在值范围[max(nums), sum(nums)]
int mx = 0;
long sum = 0;
for (int num : nums) {
mx = max(mx, num);
sum += num;
}
// 二分搜素猜子段和的最大值x
long l = mx, u = sum;
while (l <= u) {
long mid = l + (u - l) / 2;
if (enough(mid, nums, m)) {
u = mid - 1;
} else {
l = mid + 1;
}
}
return l;
}
bool enough(long x, vector<int> &nums, int m) {
// 子段和的最大值x和子段数m的关系,是关于x的递减函数count(x)
// 条件式count(x)<=m满足二分搜索的条件形式[0 0 ... 0 1 1 ...]
int count = 1;
long sum = 0;
for (int num : nums) {
sum += num;
if (sum > x) {
count++;
sum = num;
if (count > m) return false;
}
}
return true;
}