利用二分法解决,重要的地方在于看出哪里是最大值和最小值。
题目大意:给定n个值,讲这些值分成m堆,要求找出分堆之后堆的最大值,然后
从这些最大值中挑出最小值。
思路:刚开始想到的是,对这些值进行分堆,分成m堆后进行查找,但是在这一步上
就不知道怎么写代码了,只好作罢。大神给的思路是二分,还是想了好久。。
二分的优点是找出那个值,所以从这一点下手,想要找出最大值中的最小值,
就得找到它的下限和上限。将所有的值分到一个组里,则这些数值的和就
是上限,下限则是这些值中最大的那一个。因此,所求就在这个范围内,只
要根据给出的m进行分堆,利用mid值则可以找到恰好能分成m堆的那个值,此
时候,mid值即为所求了。
二分法其实就是对所求数值下手,根据题目的要求进行不断的筛选,所以最大的
要求体现在mid上,利用mid进行分堆然后判断。
#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <limits.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <functional>
using namespace std;
#define N 100050
bool search(int n,int m,int mid,int data[])
{
int i,group=1,sum=0;
for(i=0;i<n;i++)
{
sum+=data[i];
if(sum>mid) //此时mid即为此次分类的最大值
{
sum=data[i];
group++;
}
}
if(group>m)
return false; //即是判断此时的mid是否符合要求
else
return true;
}
int main()
{
int m,n,data[N],i,j;
while(cin >> n >> m)
{
int high=0,low=0,mid;
for(i=0;i<n;i++)
{
cin >> data[i];
high+=data[i];
low=low>data[i]? low:data[i];
}
mid=(low+high)/2;
while(low<high)
{
if(!search(n,m,mid,data))
low=mid+1;
else
high=mid-1;
mid=(low+high)/2;
}
cout<<mid<<endl;
}
return 0;
}