- 在 D 天内送达包裹的能力
传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。
传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。
返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。
数据范围:
1
≤
\leq
≤ D
≤
\leq
≤ weights.length
≤
\leq
≤ 50000
1
≤
\leq
≤ weights[i]
≤
\leq
≤ 500
题意:选定最小m,使得传送天数
≤
D
\leq D
≤D
思路:这道题算一下weight的sum,发现比较小,而对m的取值又满足二分的性质,所以可以很容易发现这是二分答案的做法,而pd函数有两种写法,一种是
O
(
n
)
O(n)
O(n)直接判断,一种是存储前缀和用lower_bound判断,后者均摊复杂度更小,但上界更大,所以我写了第一种。
改了三次才过样例,分别是因为:
1.max weight大于选用的m(这个也可以直接通过更改二分的lef值避免)
2.新的一天没加当前这个重量;
3.取mid的时候二进制操作写反了…
class Solution {
public:
int n;
bool pd(int m,vector<int>& weights,int& D)
{
int sum=0,ans=1;
for(int i=0;i<n;i++)
if(sum+weights[i]>m)
{
if(weights[i]>m)return false;//一次一个都不行
sum=weights[i];//选新的要放一个进去
ans++;
}
else
sum+=weights[i];
//cout<<m<<' '<<ans<<endl;
if(ans>D)return false;
return true;
}
int find(int lef,int rig,vector<int>& weights,int& D)
{
if(rig-lef<2)
{
if(pd(lef,weights,D))return lef;
return rig;
}
int mid=(lef+rig)>>1;//注意方向
if(pd(mid,weights,D))return find(lef,mid,weights,D);
return find(mid,rig,weights,D);
}
int shipWithinDays(vector<int>& weights, int D) {
n=weights.size();
int sum=0;
for(int i=0;i<n;i++)
sum+=weights[i];
return find(0,sum,weights,D);
}
};