洛谷P1182 数列分段 Section II 二分

这又是一道试了半天没过
最后学习了dalao们的题解才A的题
主要参考博客地址

思路:
答案肯定是数组中最大的数和数组中和之间的某一个数,因此就可以用二分法去找到那个数,更详细的思路见下面代码

其中,二分搜索用到的三个变量中:
left:储存二分搜索区间中最小的数(在这道题就是数组中最大的数)
right:储存二分搜索区间最大的数(在这道题中就是数组总和) 

代码:

#include<bits/stdc++.h>
using namespace std;

int n, m;	
int a[100500];

int check(int x){	//该函数是检查能否划分m个区间, 区间最大值为x 
	int sum = 0, cnt = 1;	//sum记录每个划分区间的和, cnt记录划分区间的个数 
	
	for(int i=1; i<=n; i++){
		if(sum+a[i]<=x)	//如果sum+a[i]值还小于等于x, 则加上a[i] 
			sum += a[i];
		else	//如果sum+a[i]值大于x, 区间数+1, 新区间的和sum为a[i] 
			sum = a[i], cnt++;
	}
	
	return cnt<=m;	//通过一轮划分,如果区间数小于等于m, 证明区间最大值x是可行的, 返回1 
} 

int main(){
	int left, right, mid;	//二分要用到的变量
	cin>>n>>m;
	for(int i=1; i<=n; i++){
		cin>>a[i]; 
		left = left>a[i]?left:a[i];	//找到数组中最大的数 
		right += a[i];				//计算数组总和	
	} 
	
	while(left<=right){		//开始二分搜索 
		mid = (left+right)/2;	 
		
		if(check(mid))	//检查mid作为区间最大值是否可行 
			right = mid - 1;	//可行的话, 看看能不能有更小的数可以作为区间最大值 
		else
			left = mid + 1;		//不行的话, 只能往更大的数找  
	}
	
	cout<<left<<endl;
	return 0;
} 
发布了46 篇原创文章 · 获赞 1 · 访问量 2412

猜你喜欢

转载自blog.csdn.net/weixin_43708069/article/details/104172206