首页 > 试题广场 >

过河

[编程题]过河
  • 热度指数:713 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

其中正整数 l ,表示独木桥的长度。s,t,分别表示青蛙一次跳跃的最小距离,最大距离,数组 nums 中 m 个不同的正整数分别表示这 m 个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。

数据范围:
示例1

输入

10,2,3,[2,3,5,6,7]

输出

2
感谢@17c89提供的思路
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param l int整型
     * @param s int整型
     * @param t int整型
     * @param nums int整型ArrayList
     * @return int整型
     */
    public int crossRiver (int l, int s, int t, ArrayList<Integer> nums) {
        // write code here
        if (l <= t) {
            return 0;
        }

        int result = 0;

        // 1 只能跳跃一种距离
        if (s == t) {
            for (int stone : nums) {
                if (stone % t == 0 && stone <= l) {
                    result++;
                }
            }

            return result;
        }

        // 2 可以跳跃多种距离
        // 离散化处理 <- l很大 m很小
        final int PERIOD = t * (t - 1);
        Collections.sort(nums);
        int m = nums.size();
        int[] stones = new int[m];
        int distance;
        HashSet<Integer> stoneSet = new HashSet<>();
        for (int i = 0; i < m; i++) {
            if (i == 0) {
                distance = nums.get(i);
                stones[i] = distance % PERIOD;
            } else {
                distance = nums.get(i) - nums.get(i - 1);
                stones[i] = stones[i - 1] + distance % PERIOD;
            }
            stoneSet.add(stones[i]);
        }
        distance = l - stones[m - 1];
        l = stones[m - 1] + distance % PERIOD;

        int[] dp = new int[l + t];
        Arrays.fill(dp, Integer.MAX_VALUE >> 1);

        // init
        for (int i = s; i <= t; i++) {
            if (stoneSet.contains(i)) {
                dp[i] = 1;
            } else {
                dp[i] = 0;
            }
        }

        for (int i = t + 1; i < l + t; i++) {
            for (int j = s; j <= t; j++) {
                if (dp[i - j] != Integer.MAX_VALUE >> 1) {
                    if (stoneSet.contains(i)) {
                        dp[i] = Math.min(dp[i], dp[i - j] + 1);
                    } else {
                        dp[i] = Math.min(dp[i], dp[i - j]);
                    }
                }
            }
        }

        result = Integer.MAX_VALUE;
        for (int i = l; i < l + t; i++) {
            result = Math.min(result, dp[i]);
        }

        return result;
    }
}


发表于 2025-01-03 12:35:51 回复(0)

问题信息

难度:
1条回答 440浏览

热门推荐

通过挑战的用户

查看代码
过河