• Luogu P2678跳石头


    Description:

    一年一度的“跳石头”比赛又要开始了!这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。

    Analysis:

    一般最小值最大的问题都是二分答案,初始时区间答案可能在的区间[1,L + 1],不断二分,判断中间点 mid 是否可行。至于判断,因为答案是最短的距离,所以要使所有点之间的距离大于等于 mid,从第一个点到第 n+1个点扫一遍,如果一个点到上一个点之间的距离小于mid,那么就将该点删去,最后看删去的点是否大于m。如果mid可行,那么可能会有更优的解,也就是说mid可以更大,将左端点右移;否则,删去的点太多,mid不是合法解,将右端点左移。

    Code

    #include<cstdio>
    #define N 50005
    using namespace std;
    int d[N],L,n,m;
    bool Check(int x)
    {
    	int last = 0,cnt = 0;
    	for(int i = 1;i <= n + 1;++i){
    		//each distance >= x
    		if(d[i] - d[last] < x) ++cnt;
    		else last = i;
    	}
    	if(cnt > m) return 0;
    	return 1;
    }
    void solve()
    {
    	int lb = 0,ub = L + 1;
    	while(lb + 1 < ub){
    		int mid = (lb + ub)/2;
    		//mid could be larger 
    		if(Check(mid)) lb = mid;
    		else ub = mid;
    	}
    	printf("%d
    ",lb);
    }
    int main(){
    	scanf("%d %d %d",&L,&n,&m);
    	for(int i = 1;i <= n;++i){
    		scanf("%d",&d[i]);
    	}
    	d[n + 1] = L;//Attention
    	solve();
    	return 0;
    }
    
    岂能尽如人意,但求无愧我心
  • 相关阅读:
    状压DP入门
    二分图匹配(最大匹配:匈牙利算法)
    序列自动机入门
    Trie树入门+例题(字典树,前缀树)
    扩展KMP算法(Z-Algorithm)
    Oracle锁表查询和解锁方法
    oracle获取系统日期--当前时间+前一天+当前月+前一个月
    oracle获取年月日,两个日期相减
    oracle decode函数和 sign函数
    expdp、impdp数据泵导出导入数据
  • 原文地址:https://www.cnblogs.com/Zforw/p/10698449.html
Copyright © 2020-2023  润新知