洛谷P1316 --丢瓶盖(二分答案+贪心)最小值最大化问题

题目链接

题意:
一条直线上有a个瓶盖,要选取b个瓶盖,使得选取的瓶盖中最近距离的两个瓶盖距离在所有可行方案中最大。

题目条件:
(b<=a<=100000)

分析:
一开始没看清题意,以为是要找到某个方案中,所有相邻瓶盖距离都最大,然后求这些距离中的最大距离,然后就各种想不通,最后才发现是读了个假题意。。。正确理解就是求所有可行方案中,各个方案的最小距离的最大值,那么就是最小值最大化问题。首先需要对输入的瓶盖坐标排序,然后就是二分边界确定,最小可能不可能小于0,最大不可能大于坐标最大的瓶盖与坐标最小的瓶盖的距离差值,然后就是写check函数,以mid作为该方案中瓶盖之间距离的最小值,传入mid(即估计的答案),利用贪心策略,选择出所有相邻距离大于等于mid的瓶盖,这样就可以尽可能选择多的瓶盖,然后对于可选瓶盖数大于要求选的b个瓶盖数的方案,实际选的过程可以只选b个,多的不选,这样也算是符合题意的方案,这样贪心的结果就是可以不遗漏的枚举出所有可行方案,然后就是利用二分答案,来让最小值最大化,对于二分选择的逻辑就是,如果最后得到的cnt>=b,那么我们希望所有相邻瓶盖距离都尽可能的大,这样瓶盖之间最小的距离也就尽可能的大了,这也是贪心策略,所以我们就需要让cnt变小,使它趋近于b,那么我们假定的mid,就需要变大,这样瓶盖之间距离大于等于mid的个数就会变少,也就是cnt变小。最后还是需要注意二分的写法。

主要代码

int a,b;
bool check(vector& d,int ans){
	int cnt=1,pos=0;
	for(int i=1;i=ans){
			cnt++;
			pos=i;
		}
	}
	return cnt>=b;
}
void solve(){
	vector d(a);
	for(int i=0;i>d[i];
	if(b<=1){
		cout<<"0\n";
		return;
	}
	sort(ALL(d));
	int l=0,r=d[a-1]-d[0];
	while(l>1;
		if(check(d,mid))
		l=mid;
		else
		r=mid-1;
	}
	cout<

你可能感兴趣的:(基础算法,二分算法)