题目名字 木材加工
题意
一共有n个木头,然后要将他们截成m个相等长度的木头,求能截的最大的木头的长度
思路
- 循环输入这个木头
- 进行二分,在二分模板里面进行判断,定义ans来计数,利用每个木头来除mid,用ans来进行统计这些木头被截成mid长度能被截多少段,如果大于等于m,就使边界往右移,如果,小于就往左,就能找到最大的能截得的木头长度了
算法一:二分
代码
#include<iostream>
#include<algorithm>
using namespace std;
int n,k;
const int N=1e5+5;
int a[N];
int ans=0;
int find(int l,int r)
{ while(l<=r){
int mid=l+r>>1;
int ans=0;
for(int i=0;i<n;i++){
ans+=a[i]/mid;
}
if(ans>=k){
l=mid+1;
}
else{
r=mid-1;
}
}
return r;
}
int main(){
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
int l=1,r=a[n-1];
int x=find(l,r);
cout<<x;
return 0;
}
算法二:二分
思路
通过find二分来找范围内最大的函数,先定义全局变量,数组和输入的n,k,再用find函数进行查找l和r,进行for循环遍历每一个木棍进行计算在不同的mid之下可以切割的木头数量,并且用ans来计数,确保输出的在k范围之内,接下去就是while循环,在(l<=r)范围内进行二分查找,(注意ans要定义在while函数上面,保证每次遍历ans都要初始化,否测ans在每一次遍历上一直叠加),用一个result来记录最大值,返回最大值即return result;
|
ps:为什么不需要再条件ans要小于k呢,是由于二分查找已经包含这个判断啦,ans大于k时范围就会往左移动,所以直接return最大值就好啦,要是超出了给定范围,这个值是不会被保留哒
|
主函数部分主要呢,就是注意用sort函数来遍历一遍所有数组,并且要定义一个值来调用find函数,就OK了
还有调用find函数可以不用定义l和r的值,直接在定义值的时候,在find函数中输入l和r的值即可
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,k;
int a[N];
int find (int l,int r)
{
int result=0;
while(l<=r){
int mid=l+r>>1;
int ans=0;
for(int i=0;i<n;i++){
ans+=a[i]/mid;
}
if(ans>=k){
result=mid;
l=mid+1;
}
else{
r=mid-1;
}
}
return result;
}
int main(){
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
int l=1,r=a[n-1];
int x=find(1,r);
cout<<x;
return 0;
}
总结
主要是复习了一遍二分,关于各个函数的调用还有用法,不同代码存在的理解,基本没有大问题,如果有一天又忘记了,请看笔记谢谢。这道题还要注意r的范围是a[n-1],最大的那个数字,就是最大的范围边界,考试的时候拜托一定想起来啊啊啊