• 【POJ No. 3258】 跳房子游戏 River Hopscotch


    POJ No. 3258】 跳房子游戏 River Hopscotch

    POJ题目地址

    在这里插入图片描述

    【题意】

    跳房子游戏指从河中的一块石头跳到另一块石头,这发生在一条又长又直的河流中,从一块石头开始,到另一块石头结束。长度为L (1≤L ≤10^9 ),从开始到结束之间的石头数量为N (0≤N ≤50 000),从每块石头到开始位置有一个整数距离di(0

    为了玩游戏,每头母牛都依次从起始石头开始,并尝试到达终点的石头,只能从石头跳到石头。当然,不那么灵活的母牛永远不会到达最后的石头,而是掉进河中。约翰计划移除几块石头,以增加母牛必须跳到最后的最短距离。不能删除起点和终点的石头,但约翰有足够的资源移除多达M 块石头(0≤M ≤N )。请确定在移除M 块石头后,母牛必须跳跃的最短距离的最大值。

    【输入输出】

    输入:

    第1行包含3个整数L 、N 和M 。接下来的N 行,每行都包含一个整数,表示从该石头到起始石头的距离。没有两块石头有相同的位置。

    输出:

    单行输出移除M 块石头后母牛必须跳跃的最短距离的最大值。

    【样例】

    在这里插入图片描述

    【思路分析】

    根据输入样例,构建的图如下图所示。

    在这里插入图片描述

    在移除任何石头之前,跳跃的最短距离都是2(从0到2)。在移除2和14石头后,跳跃的最短距离是4(从17到21或从21到25)。

    在这里插入图片描述

    算法设计

    ① 如果移除的石头数等于总石头数(M =N ),则直接输出L 。

    ② 增加开始(0)和结束(N +l)两块石头,到开始节点的距离分别为0和L 。

    ③ 对所有的石头都按照到开始节点的距离从小到大排序。

    ④ 令left=0,right=L ,如果right-left>1,则mid=(right+left)/2,判断是否满足移除M 块石头之后,任意间距都不小于mid。如果满足,则说明距离还可以更大,令left=mid;否则令right=mid,继续进行二分搜索

    ⑤ 搜索结束后,left就是母牛必须跳跃的最短距离的最大值。

    【举个栗子】

    ① 根据输入样例,增加开始和结束两块石头,按照到开始节点的距离从小到大排序。

    在这里插入图片描述

    ② 令left=0,right=L =25,right-left>1,mid=(right+left)/2=12,判断是否满足移除两块石头之后,任意间距都不小于12。相当于将3块石头放置在开始位置和结束位置之间,且满足任意间距都不小于12。

    用last记录前一块已放置石头的下标,初始时last=0,找第1个与last距离大于或等于12的位置,找到14,放置第1块石头,更新last=3。

    在这里插入图片描述

    继续找第1个与last距离大于或等于12的位置,未找到,说明无法满足条件。缩小距离,令right=mid=12,继续搜索。

    ③ left=0,right=12,mid=(right+left)/2=6,判断是否满足移除两块石头之后,任意间距都不小于6。初始时last=0,找第1个与last距离大于或等于6的位置,找到11,放置第1块石头,更新last=2。

    在这里插入图片描述

    继续找第1个与last距离大于或等于6的位置,找到17,放置第2块石头,更新last=4。

    在这里插入图片描述

    ④ left=0,right=6,mid=(right+left)/2=3,判断是否满足移除两块石头之后,任意间距都不小于3。初始时last=0,找第1个与last距离大于或等于3的位置,找到11,放置第1块石头,更新last=2。

    在这里插入图片描述

    继续找第1个与last距离大于或等于3的位置,找到14,放置第2块石头,更新last=3。

    在这里插入图片描述

    继续找第1个与last距离大于或等于3的位置,找到17,放置第3块石头,可以放置3块石头,满足条件。增加距离,令left=mid=3,继续搜索。

    在这里插入图片描述

    ⑤ left=3,right=6,mid=(right+left)/2=4,判断是否满足移除两块石头之后,任意间距都不小于4。初始时last=0,找第1个与last距离大于或等于4的位置,找到11,放置第1块石头,更新last=2。

    在这里插入图片描述

    继续找第1个与last距离大于或等于4的位置,找到17,放置第2块石头,更新last=4。

    在这里插入图片描述

    继续找第1个与last距离大于或等于4的位置,找到21,放置第3块石头,可以放置3块石头,满足条件。增加距离,令left=mid=4,继续搜索。

    ⑥ left=4,right=6,mid=(right+left)/2=5,判断是否满足移除两块石头之后,任意间距都不小于5。初始时last=0,找第1个与last距离大于或等于5的位置,找到11,放置第1块石头,更新last=2。

    在这里插入图片描述

    继续找第1个与last距离大于或等于5的位置,找到17,放置第2块石头,更新last=4。

    在这里插入图片描述

    继续找第1个与last距离大于或等于5的位置,未找到,说明无法满足条件。缩小距离,令right=mid=5,继续搜索。

    ⑦ left=4,right=5,此时right-left=1,算法结束,输出答案left=4。

    【算法实现】

    判断函数相当于将n -m 块石头放置在开始位置和结束位置之间,且任意间距都不小于x 。

    #include
    #include
    
    using namespace std;
    
    const int maxn = 50050;
    int L ,n , m , dis[maxn];
    
    bool judge(int x ){ //移除m 个 石头之后,任意间距不小于x 
    	
    	int num = n - m; //减掉m 个石头,放置num 个石头,循环num 次
    	int last = 0; //记录前一个已放置石头下标 
    	
    	for(int i = 0 ; i < num ; i++){ //对于这些石头,要使得任意间距不小于x 
    		
    		int cur = last + 1;
    		while(cur <= n && dis[cur] - dis[last] < x){ //放在第1个与last距离>=x 的位置 
    			
    			cur ++; //由cur 累计位置	
    		}
    		
    		if(cur > n){
    			return 0; //如果在这个过程中大于n 了,说明放不开 
    		}
    		last = cur; //更新last 位置 
    	}
    	return 1;
    }
    
    int main(){
    	
    	cin >> L >> n >> m;
    	if(n == m){
    		
    		cout << L << endl;
    		return 0;
    	}
    	
    	for(int i = 1 ; i <= n ; i++){
    		
    		cin >> dis[i];
    	}
    	dis[0] = 0; //增加开始点
    	dis[n + 1] = L; //增加结束点
    	
    	sort(dis , dis + n + 2);
    	int left = 0 , right = L;
    	
    	while(right - left > 1){
    		
    		int mid = (right + left) / 2;
    		if(judge(mid)){
    			
    			left = mid; //如果放得开,说明x 还可以更大 
    		}
    		else{
    			
    			right = mid;
    		}
    	} 
    	
    	cout << left << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    在这里插入图片描述

  • 相关阅读:
    MongoDB命令
    【SQL】实现读写分离的分配的方式
    旅游网页设计 web前端大作业 全球旅游私人订制 旅游公司网站模板(HTML+CSS+JavaScript)
    nvm管理node版本 nodenpm不是内部或外部命令,也不是可运行的程序
    巨细靡遗流程控制,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang流程结构详解EP09
    零基础Linux_20(进程信号)内核态和用户态+处理信号+不可重入函数+volatile
    设计模式系列之MVC模式
    如何参与开源项目 - 细说 GitHub 上的 PR 全过程
    使用vue3前端开发的一些知识点
    C++之STL基础概念、容器、数据结构
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/127666536