二分查找之求最大值的最小值

题目链接:点击这里

看到题目中的“最大值最小”就知道这题主要考察的是用二分法求满足条件的最小值

所以关于mid的求法如下:

while(l < r)
{
	mid = (l + r)/2;//注意是(l+r)
	if(judge(mid))//符合条件
		r = mid;
	else
		l = mid + 1;
}

 

其中的

mid = (l + r)/2;

 

详情请见大佬的博客

关于"L"和"R"的选取:

每段和的最大值的最小的情况就是把每个数当做单独的一段其中最大的一个,每段和的最大值的最大的情况就是把所有的数当成一段,即所有数的和

接下来就是"judge"这个函数该怎么写:

我的想法是用一个变量来计数,统计以当前mid作为每一段和的最大值时会划分出多少段,如果统计出的数量小于等于规定的段数,说明当前的mid是可行的,但未必是最小的,所以接着二分。代码如下:

bool judge(int x)//传入mid
{
	int num = 0,sum = 0;
	int i;
	for(i = 1;i <= N;i++)
	{
		sum += a[i];
		if(sum > x)//当前累加的和大于mid,说明到a[i]的前一个为止是一段
		{
			i --;//回溯一个,下一步循环从当前的a[i]开始累加
			num ++;//统计段数
			sum = 0;//重新开始计数
		}
		
	}
	if(sum)//注意:最后一段的累加值若小于等于mid在上面的循环中不会计数,这里加上
		num++;
	return num <= M;
}

最后,附上全部代码:

#include<cstdio>
#define Max 100002
int N,M,a[Max];
 
bool judge(int x)
{
	int num = 0,sum = 0;
	int i;
	for(i = 1;i <= N;i++)
	{
		sum += a[i];
		if(sum > x)
		{
			i --;
			num ++;
			sum = 0;
		}
		
	}
	if(sum)
		num++;
	
	return num <= M;
}
 
int main()
{
	scanf("%d%d",&N,&M);
	int i,max=0,sum=0;
	for(i = 1;i <= N;i++)
	{
		scanf("%d",&a[i]);
		sum += a[i];
		if(a[i] > max)
			max = a[i];
	}
	int l,r,mid;
	l = max;
	r = sum;
	while(l < r)
	{
		mid = (l + r)/2;
		if(judge(mid))
			r = mid;
		else
			l = mid + 1;
	}
	
	printf("%d",r);
	
	return 0;
}

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值