题意:对给给出的n个数,划分为m块,使每一块中所有数的和的最大值最小,是经典的最大值最小问题。
一些思考:
用到二分我也觉得一开始没想到,现在觉得确实用二分挺合理的
1.即首先求出二分的上下限,这个是每次二分必做的准备工作,
上限即为这一堆东西的总量,下限即单个最大的物品的值。
2.有上下限之后即开始二分,最难写的部分就出来了,即判断当前分堆是否合理,在判断分堆是否合理中,主要的限制因素为两个,一个是单堆的量肯定不能超过当前的Mid值,另一个是分出的堆数一定不能超过题目要求的M值
3.由判断条件即可将二分范围进行缩小,即,一旦当前Mid值满足分堆要求,意味着我还可以把Mid值缩小,即把二分的right=mid,如果当前Mid值触犯了判断条件,即说明当前值还太小,即把left=mid。
4.由以上二分return出来的结果即为所求值
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
#include<algorithm>
using namespace std;
const int maxn=100006;
int a[maxn];
int n;
int a[maxn];
int n;
int judge(int x){
int now=0;
int cnt=1;
for(int i=0;i<n;i++){
if(now+a[i]>x){
cnt++;
now=a[i];
}else{
now+=a[i];
}
}
return cnt;
}
int now=0;
int cnt=1;
for(int i=0;i<n;i++){
if(now+a[i]>x){
cnt++;
now=a[i];
}else{
now+=a[i];
}
}
return cnt;
}
int main(){
int m,l=0;
int sum=0;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
l=max(l,a[i]);
sum+=a[i];
}
int r=sum;
int mid;
while(l<r){
mid=(l+r)/2;
int num=judge(mid);
if(num<=m){
r=mid;
}else{
l=mid+1;
}
}
printf("%d\n", r);
}
int m,l=0;
int sum=0;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
l=max(l,a[i]);
sum+=a[i];
}
int r=sum;
int mid;
while(l<r){
mid=(l+r)/2;
int num=judge(mid);
if(num<=m){
r=mid;
}else{
l=mid+1;
}
}
printf("%d\n", r);
}