洛谷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<int>& d,int ans){
	int cnt=1,pos=0;
	for(int i=1;i<a;i++){
		if(d[i]-d[pos]>=ans){
			cnt++;
			pos=i;
		}
	}
	return cnt>=b;
}
void solve(){
	vector<int> d(a);
	for(int i=0;i<a;i++)
	cin>>d[i];
	if(b<=1){
		cout<<"0\n";
		return;
	}
	sort(ALL(d));
	int l=0,r=d[a-1]-d[0];
	while(l<r){
		int mid=(l+r+1)>>1;
		if(check(d,mid))
		l=mid;
		else
		r=mid-1;
	}
	cout<<l<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值