题目大意:给定n个数据,将这n个数据分成m组,使得每组数据值和尽可能的小,输出所有组中最大的和。解法很巧妙,开始的时候没想到用二分法解,想暴力枚举过。。后来看了别人的解题报告,就考虑率用二分法解。题目在选取元素的时候很巧妙,用着n个数据分为一组最大的值到n个数据之和,作为二分的对象,这样必然有序,然后是选取改变上下界的函数,这里采用给定一个分法的上界,看起分组的个数与给定的要求的分组个数的关系。从这个角度考虑,那么问题的解就是区间[x,y](该区间能满足上述条件)的最左端的元素即x。然后主体算法就与找二分查找元素中的下界。
代码:
#include <iostream>
#include <stdio.h>
using namespace std ;
const int maxn = 100005 ;
int num[maxn] ;
bool func(int ) ;
int n ;
int m ;
int main()
{
int i ;
int j ;
int x ;
int y ;
int v ;
while(scanf("%d%d" , &n , &m)!=EOF)
{
x = 0 ;
y = 0 ;
for(i = 0 ; i < n ; i ++)
{
scanf("%d" , &num[i]) ;
if(x < num[i])
x = num[i] ;
y += num[i] ;
}
while(x < y)
{
v = x + (y-x)/2 ;
if(func(v))//偏小,则向后移动
x = v + 1 ;
else //偏大,则向前移动
y = v ;
}
printf("%d\n" , x) ;
}
return 0 ;
}
bool func(int x)
{
int i ;
int sum ;
int cont ;
sum = 0 ;
cont = 1 ;
for(i = 0 ; i < n ; i ++)
{
if(sum + num[i] <= x)
sum = sum + num[i] ;
else
{
sum = num[i] ;
cont ++ ;
}
}
if(cont > m)//分多了,说明给定的值偏小
return true ;
//说明分少了,给定的值偏大
return false ;
}