Leetcode 1011-Capacity To Ship Packages Within D Days
题干:
传送带上有一堆货物( n n n个)要装载到船上运到对岸,第 i i i个货物的重量是 w e i g h t s [ i ] weights[i] weights[i]。
船的载重量为 x x x,船上装在的货物重量之和不会超过船的载重量。货物是按传送带上的顺序依次放在船上的。对于货物 i i i,如果当前船可以继续装它,那么该货物可以装到这个船上;如果当前船装不下了,该货物(及其后面的货物)就要等下一辆船。
一天只有一辆船停在港口。如果想在 d a y s days days天内把货物全部运到对面,求船所需要的最小载重量。
Input: weights = [1,2,3,4,5,6,7,8,9,10], days = 5
Output: 15
Explanation: A ship capacity of 15 is the minimum to ship all the packages in 5 days like this:
1st day: 1, 2, 3, 4, 5
2nd day: 6, 7
3rd day: 8
4th day: 9
5th day: 10
解:
设船的载重量为 x x x。可以得到,船的载重量越大,运送货物所需要的天数越少;船的载重量越少,运送货物所需要的天数越多。所以船的载重量和运送货物所需要的天数是一个单调不递增关系。
所以,可以定义 f ( x ) f(x) f(x)为:以载重量为 x x x的船运送货物,所需要的天数。
又由题,需要限制 f ( x ) ≤ d a y s f(x)\le days f(x)≤days。
所以该题所求的是:满足 f ( x ) ≤ d a y s f(x) \le days f(x)≤days的条件下的最小 x x x。画图可得求的是左边界。
x x x的取值范围: l e f t = m a x ( w e i g h t s [ i ] ) , r i g h t = ∑ w e i g h t s [ i ] left=max(weights[i]), right=\sum weights[i] left=max(weights[i]),right=∑weights[i]
int f(vector<int>& weights, int x){
int cnt = 1, res = x;
for(int w: weights){
if(res < w){
++cnt;
res = x;
}
res -= w;
}
return cnt;
}
int shipWithinDays(vector<int>& weights, int days) {
int left = 0, right = 0;
for(int w: weights){
left = max(left, w);
right += w;
}
right += 1; //因为是右开区间
int ans = right;
while(left < right){
int mid = left + ((right - left) >> 1);
int d = f(weights, mid);
if(d <= days){
ans = mid;
right = mid;
}
else if(d > days) left = mid + 1;
}
return ans;
}