贪心算法之——摘枇杷(nyoj680)(贪心+二分搜索)

问题:

摘枇杷

时间限制: 2000 ms  |  内存限制: 65535 KB
难度: 3
描述

理工学院的枇杷快熟了,ok,大家都懂得。而且大家都知道,学校的枇杷树都是一列一列的。现在小Y同学已经在筹划怎么摘枇杷了。现在我们假设有一列枇杷树,而且每棵枇杷树上枇杷果的数量小Y都已经知道了。

假设现在有n棵枇杷树,小Y可以把这n棵枇杷树分成m组,每组枇杷果的数量是这组内每棵枇杷树上枇杷果数量的和。注意,每组的枇杷树必须是连续的。(每组最少1棵树,最多n棵树)。小Y把枇杷往寝室拿的时候是一组一组拿的,所花费的力气等于这m组中枇杷果最多的那组枇杷果的数量。现在小Y想花尽量少的力气把这些枇杷果拿回寝室。

输入
多组测试数据,以EOF结束(<= 100组)
每组测试数据第一行有两个数n(n <= 1000)和m(1 <=m <= n)
第二行有n个数,分别代表每颗树上枇杷果的数量
输出
输出小Y同学所花费的最小的力气,每个结果占一行。
样例输入
3 2
1 2 3
7 5
1 4 3 1 5 2 4
样例输出
3
5

分析:

这是一个最大值最小化的问题。

当m==1时,result==sum==a[0]+a[1]+a[2]+……+a[n-1]

当m==n时,result==max(a[]) (数组中的最大值)

当m>1&&m<n时,我们就可以通过二分搜索从max(a[]) ~ sum中枚举出m组时的最小值


代码:

#include <stdio.h>
#include <string.h>
int n, m, a[1005], sum, Max;
bool judge(int x)
{
	int s=0,count=0;
	for(int i=0; i<n; i++)
	if(s+a[i]>x)
	{
		count++;
		s=a[i];
		if(count>m-1) //当count==m时,而i<n, 则当每次运送x时,m组内运不完 
			return false;
	}
	else
		s += a[i];
	return true;	//每次运送x时,m组内就能运完 
}
int get_ans()
{
	int l=Max, r=sum; //n==m时,最大为Max,当m==1时,最大为sum 
	while(l<=r)
	{
		int mid = (l+r)/2;
		if(judge(mid)) r = mid-1;
		else l = mid+1;
	}
	return l;	//当从while中退出时,最后一次操作是r=mid-1,原本的l<=r不再满足 ,所以l才是所要求的值 
}
int main()
{
	while(~scanf("%d%d", &n, &m))
	{
		memset(a,0,sizeof(a));
		Max=0; sum=0;
		for(int i=0; i<n; i++)
		{
			scanf("%d", &a[i]);
			sum += a[i];
			Max = Max>a[i]?Max:a[i];
		}
		printf("%d\n", get_ans());
	} 
	return 0;
}





你可能感兴趣的:(二分搜索,贪心算法)