题意:按顺序给你N个数,将这N个数分成连续的M段,使得这M段每段的和中的最大值最小,输出最小值。(1<=N<=100000,1<=M<=N,每个数在1到10000之间)
解题思路:不管分成多少段,每种分法和的最大值都在N个数的最大值和N个数的和之间。所求答案也在这之间。
我们可以以此为上下界,二分M段和的最大值进行尝试。对每次二分的值,将数组扫描累加。若当前和大于二分的这个值,则段数加一,由此统计出在当前值下,N个数能够分成的最小段数。若这个段数小于或等于M,则向上界变为mid-1,并记下当前mid的值。否则,下界变为mid+1。继续二分,直到退出循环。最后记录的mid值即为答案。
代码:
#include <stdio.h>
int money[100001];
int main()
{
int N,M,i,j;
int sum,count,max;
int low,high,mid;
while(scanf("%d%d",&N,&M)!=EOF)
{
sum=0;max = -1;
for(i = 0;i<N;i++)
{
scanf("%d",&money[i]);
if(money[i]>max)
max = money[i];
sum+=money[i];
}
low = max;
high = sum;
while(low<=high)
{
mid = (low+high)/2;
sum = 0;count = 1;
for(i = 0;i<N;i++)
{
sum+=money[i];
if(sum>mid)
{
sum = money[i];
count++;
}
}
if(count<=M)
{
max = mid;
high = mid-1;
}
else
low = mid+1;
}
printf("%d\n",max);
}
return 0;
}