HDU 4004 Frog‘s games(贪心+二分)超详细

题目描述:

The annual Games in frogs' kingdom started again. The most famous game is the Ironfrog Triathlon. One test in the Ironfrog Triathlon is jumping. This project requires the frog athletes to jump over the river. The width of the river is L (1<= L <= 1000000000). There are n (0<= n <= 500000) stones lined up in a straight line from one side to the other side of the river. The frogs can only jump through the river, but they can land on the stones. If they fall into the river, they are out. The frogs was asked to jump at most m (1<= m <= n+1) times. Now the frogs want to know if they want to jump across the river, at least what ability should they have. (That is the frog's longest jump distance).

Input The input contains several cases. The first line of each case contains three positive integer L, n, and m. Then n lines follow. Each stands for the distance from the starting banks to the nth stone, two stone appear in one place is impossible.

Output For each case, output a integer standing for the frog's ability at least they should have.
样例输入:

6 1 2

2

25 3 3

11

2

18

大意: 这段描述是一道关于青蛙跳河问题的题目描述,其中包含了输入格式和输出要求的说明。

  • 输入格式:每个测试用例的第一行包含三个正整数 L、n 和 m,分别表示河的宽度、石墩数量和最大跳跃次数。接下来的 n 行每行包含一个整数,表示从起始岸到第n块石头的距离。

  • 输出格式:对于每个测试用例,输出一个整数,表示青蛙至少应该具备的能力,即能够跳过整条河的最小跳跃距离。

Sample Input 


6 1 2

2

25 3 3

11

2

18

Sample Output

4

11

这个样例输入包含两个测试用例,分别是:

  1. 河的宽度为6,有1块石头,最多可以跳2次,石头距离起始点的距离为2。
  2. 河的宽度为25,有3块石头,最多可以跳3次,石头距离起始点的距离分别为11、2、18。

 解决方案:

思路:1.先初始化河的宽度,石墩的数量,最大有跳跃次数;
           2.将石墩的位置存入数组中,读取每个石墩到起点的位置存入数组a[i],并按远近进行大小排序。
           3.二分查找,求mid = (l + r) / 2;;

  check该mid值是否符合条件:
    ① i <= n && a[i] - dis <= mid :
        i <= n:保证当前石墩位置索引i不超过石墩数量n,即仍然存在石墩可以跳跃到。
        a[i] - dis <= s:保证从当前位置跳跃到下一个石墩的距离不超过最大跳跃距离s。这个条件确 
保青蛙可以跳跃到下一个石墩而不会超出最大跳跃范围

   ② step > m(跳跃次数超过最大次数m)
         4.如果  mid大了 ;r = mid - 1;  缩小搜索范围
                  mid小了 ;l = mid + 1;  扩大搜索范围
         5.  注意记得每次更新当前位置 :   dis = a[i - 1];  
 

 代码展示和思路:

package 青蛙游戏;


//思路:1.先初始化河的宽度,石墩的数量,最大有跳跃次数;
//    2.将石墩的位置存入数组中,读取每个石墩到起点的位置存入数组a[i],并按远近进行大小排序。
//    3.二分查找,求mid = (l + r) / 2;;
//      check该mid值是否符合条件:
//      ① i <= n && a[i] - dis <= mid :
//        i <= n:保证当前石墩位置索引i不超过石墩数量n,即仍然存在石墩可以跳跃到。
//        a[i] - dis <= s:保证从当前位置跳跃到下一个石墩的距离不超过最大跳跃距离s。这个条件确 
//保青蛙可以跳跃到下一个石墩而不会超出最大跳跃范围
//      ② step > m(跳跃次数超过最大次数m)
//    4.如果  mid大了 ;r = mid - 1;  缩小搜索范围
//            mid小了 ;l = mid + 1;  扩大搜索范围
//    5.  注意记得每次更新当前位置 :   dis = a[i - 1];  


import java.util.*;

public class HDU_4004 {
    public static int[] a; // 用于存储石墩位置的数组
    public static int L, n, m; // 河的宽度、石墩数量、最大跳跃次数

    // 检查是否满足条件的方法
    public static boolean check(int s) {
        int dis = 0, i = 0, step = 0;
        while (dis < L && i <= n) {
            // 在跳跃距离不超过s的情况下尽可能多地跳跃到石墩上
            while (i <= n && a[i] - dis <= s) {
                i++;
            }
            step++; // 记录跳跃次数
            dis = a[i - 1]; // 更新当前位置
            if (step > m) return false; // 如果跳跃次数超过最大次数m则返回false
        }
        return true; // 能够在跳不超过m次的情况下到达终点,返回true
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            L = scanner.nextInt(); // 读取河的宽度
            n = scanner.nextInt(); // 读取石墩数量
            m = scanner.nextInt(); // 读取最大跳跃次数

            a = new int[n + 1]; // 初始化石墩位置数组
            for (int i = 0; i < n; i++) {
                a[i] = scanner.nextInt(); // 读取每个石墩的位置
            }
            a[n] = L; // 设置终点位置为河的宽度
            Arrays.sort(a, 0, n); // 对石墩位置进行排序

            int l = 0, r = 1000000000, ans = 0; // 初始化二分查找的左右边界和答案
            while (l <= r) {
                int mid = (l + r) / 2; // 计算中间值
                if (check(mid)) { // 判断是否满足条件
                    ans = mid; // 更新答案为当前距离
                    r = mid - 1; // 缩小搜索范围
                } else {
                    l = mid + 1; // 扩大搜索范围
                }
            }
            System.out.println(ans); // 输出结果,即青蛙至少要跳的最小距离
        }
        scanner.close(); // 关闭Scanner
    }
}


  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值