给定N个木头及其长度,要求把这些木头切割成M块长度相同的小段木头(木头有可能有剩余),求小段木头的最大值。
比如:有两木头长度为 11 和 21, 要求切成 6 块, 那么每块最长就为 5。
1 ≤ N ≤ 100000 , 1 ≤ M ≤ 100000000 1 ≤ N ≤ 100000,1 ≤ M ≤ 100000000 1≤N≤100000,1≤M≤100000000
原 木 长 度 : 1 到 100000000 原木长度:1到100000000 原木长度:1到100000000
我们没有办法直接根据木块长度,和要切的块数去算最终小木块的长度。
最终小木块的长度只能在 0 到 100000000 之间。
不考虑时间复杂度,我们可以枚举木块长度,判断寻找可行长度的最大值。
但很明显这个问题的答案具有单调性,也就是说我们不用枚举木块长度,可以二分查找。
为什么说有单调性呢?
因为假设当前进行判断的木块长度为X,如果长度X可行,那么最终答案肯定大于等于X,如果X不可行,那么最终答案肯定小于X。
所以我们可以对 0 到 100000000 这个答案区间进行二分查找,准确来说是右边界二分查找,找到满足要求的最大值。
右边界二分(17ms)
#include
using namespace std;
int n,m;
int a[100005];
bool check(int x)
{
if(x==0)//长度为0肯定可行
return true;
int ans = 0;
//累加当长度为x时,能切成的块数
for(int i = 1; i <= n; ++i){
ans += a[i]/x;
}
//大于等于m则表示可行
return ans >= m;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; ++i)
cin >> a[i];
int l = 0;
int r = 100000001;
//右边界二分
while(l<r){
int mid = l+(r-l)/2;
if(check(mid))//判断mid是否满足要求
l = mid+1;
else
r = mid;
}
cout << r-1 << endl;
return 0;
}