题目链接:F-华华给月月准备礼物_2021秋季算法入门班第三章习题:二分、三分、01 (nowcoder.com)
事先声明一下,这题本人的答案结果超时了,所以这里仅供读者当练习使用,文章如有不当之处恳请大佬们完善。
题目要求:输入正整数N和K,分别表示原本根数和希望根数,再自己输入各根木头的长度。
输出结果为裁剪后可获得的最大长度。
思路:二分法——这题要在保证数目的情况下越长越好,所以为了避免出现长度太长 一些短根的木棍无法裁剪从而导致数量减少的情况,我们需要找到最短的那根木棍,再对这跟木棍的长度进行二分处理,经过不断二分找到符合最后根数的最大长度。
首先,定义一个容器来储存原有的木棍
然后再找到这些木棍中最短的那根木棍
找到最短木棍后对他的长度进行二分处理,设定mid=(l+r)/2,如果得出的根数多了则说明短了,mid值右移 l=mid,反之相反。
现在是对mid值进行处理,确定改mid值下可以裁剪出多少根木棍出来。裁剪的根数=每根木棍的长度/mid,将所有根数做累加就是总根数
接下来是完整的代码实现
#include<bits/stdc++.h>
using namespace std;
int N,k,n;
vector<int> L;
int work(int x)//确定能总共能切多少根
{
int gs=0;
for(vector<int>::iterator it=L.begin();it!=L.end();it++)
{
gs=gs+(*it/x);//每根能切出的根数
}
return gs;
}
int main()
{
cin>>N>>k;//输入原本的根数N和希望获得的根数K
for(int i=0;i<N;i++)
{
cin>>n ;
L.push_back(n);
}
int min;
min=L[0];
for(vector<int>::iterator it=L.begin();it!=L.end();it++)
{
if(min>*it)min=*it;//找到这些木棍中最短的那根
}
int l=1,r=min;
while(l+1!=r)
{
//对最短的那一根长度进行二分
int mid=l + ((r - l) >> 1);
if(work(mid)<=k)r=mid;
else l=mid;
}
cout<<l;
}
如先前所说这段代码是超时的,还恳请看到的大佬指出哪里可以优化