P2678 跳石头(贪心+二分答案)

题目描述

在这里插入图片描述
在这里插入图片描述

分析

遇到最短距离的最大值,用二分
通过遍历最短跳跃距离来用贪心策略计算需要挪走的岩石,来与M值比较。
直接遍历超时,用二分法。
首先,二分的范围:最短为岩石之间或者岩石与岸边的最小距离;最大为整个比赛的长度。
由题意得,最短跳跃距离越大,需要挪走的岩石越多,正相关,递增序列。
要找最短距离的最大值,就要找到最后一个小于等于M值(要挪走的岩石数)

代码

#include<bits/stdc++.h> 
typedef long long ll;
using namespace std;
const int maxn = 5e4+50;
ll c,n,m,a[maxn],minall = maxn,ans;
bool check(int t){
    
    	//贪心策略计算需要挪走的岩石数目 
	ll flag = 0;
	ll sum = 0;
	int i = 1;
	while(i <= n+1){
    
    
		ll len = a[i] -a[i-1] + sum;
		if(len < t){
    
    
			flag++;
			sum = len;
		}
		else{
    
    
			sum = 0;
		}
		i++;
	}
	if(flag > m){
    
    
			return false;
	}
	return true;
}
int main(){
    
    
	//freopen("a.txt","r",stdin); 
	cin>>c>>n>>m;
	for(int i = 1;i<= n;i++){
    
    
		cin>>a[i];
		minall = min(minall,i==1?0:a[i]-a[i-1]);
	}
	
	a[0] = 0;
	a[n+1] = c;
	
	ll l = minall ,r = c;
	//找到最后一个小于等于M的值。 
	while(l <= r){
    
    
		ll mid = l + (r-l)/2;	//防止溢出 
		if(check(mid)){
    
    
			l = mid+1;
			ans = mid;
		}
		else{
    
    
			r = mid-1;
		}
	}
	cout<<ans<<endl;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/m0_45210226/article/details/108292402