[CSP2020 山东小学组]勇敢的津津

[CSP2020 山东小学组]勇敢的津津
津津是个勇敢的人,总是做一些挑战自己的事情。
一天津津来到一条宽为 L 米的小河边,河道的一边到另一边需要途径 N 块较大的石墩,每块石墩到这一边岸边之间距离 xi 米(石墩不占距离,只考虑石墩的中间点到这一边岸边之间距离)。
津津想踩着这些石墩从小河的这一边跳到另一边(不落入水中),一次可以跳过几块石墩。
已知津津每次最多跳 M 米的距离,那么津津最少跳几次就能从这一边跳到另一边?
输入描述
第一行包含三个整数 L,N, M,分别小河的宽度、石墩数和津津跳的最远距离。
接下来 N 行,每行一个整数,第 i 行的整数 di( 0 <di < L), 表示第 i 块石墩与这一边岸边的距离,保证石墩之间的距离和石墩到这一边岸边的距离小等于 M。这些石墩按与起点距离从小到大的顺序给出,且不会有两个石墩出现在同一个位置。
输出描述
一个整数,即最少的跳跃次数。
样例输入 1
10 4 2
2
4
6
8
样例输出 1
5
样例输入 2
25 5 10
2
11
14
17
21
样例输出 2
4
提示
【样例解释】
样例一:津津可以从岸边跳到距离为 2 石墩上,然后跳到距离为 4 的石墩上,再跳到距离为 6 的石墩上,再跳到距离为 8 的石墩上,最后跳的对岸。总共 5 跳跃。

样例二:津津可以从岸边跳到距离为 2 石墩上,然后跳到距离为 11 的石墩上,再跳到距离为 21 的石墩上,最后跳的对岸。总共 4 跳跃。
【数据范围】
对于 30% 的数据,1≤N≤10。
对于 50% 的数据,1≤N≤100。
对于 100%的数据,1≤N≤500,1≤M,L≤1,000,000。


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int min_jumps(int L, int N, int M, vector<int>& distances) {
    sort(distances.begin(), distances.end());  // 将石墩的距离按与起点的距离从小到大排序
    int cur_pos = 0;
    int steps = 0;

    for (int i = 0; i < N; i++) {
        int diff = distances[i] - cur_pos;  // 当前石墩与起点的距离
        if (diff <= M) {
            cur_pos = distances[i];  // 可以直接跳到该石墩上
            steps++;
        } else {
            int max_dist = 0;
            int next_pos = cur_pos;
            for (int j = cur_pos; j < distances[i]; j++) {
                int dist = j - cur_pos;  // 计算当前位置与当前石墩的距离
                if (dist <= M && dist > max_dist) {
                    max_dist = dist;
                    next_pos = j;
                }
            }

            cur_pos = next_pos;
            steps++;
        }
    }

    return steps;
}

int main() {
    // 样例输入 1
    int L1 = 10, N1 = 4, M1 = 2;
    vector<int> distances1 = {2, 4, 6, 8};
    cout << min_jumps(L1, N1, M1, distances1) << endl;  // 输出 5

    // 样例输入 2
    int L2 = 25, N2 = 5, M2 = 10;
    vector<int> distances2 = {2, 11, 14, 17, 21};
    cout << min_jumps(L2, N2, M2, distances2) << endl;  // 输出 4

    return 0;
}

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/7754940
  • 除此之外, 这篇博客: 动态规划及其应用中的 ,剩2的容量就拿不了钻石,而拿三件大衣价值才三四十块钱,所以,要一件一件的递增,递增到两件大衣时,剩容量8,不就可以多拿几个钻石,这多好啊。所以要看看到底拿几件时才能达到最优解。而不是一下尽可能多拿 部分也许能够解决你的问题。
  • 以下回答由chatgpt基于相关博客总结生成:

    首先我们可以通过分析问题来设计算法。假设津津站在起点,我们需要找到一种最优的方案,使得津津能够最少跳跃次数从起点跳到终点。根据题目描述,津津每次最多跳M米的距离,因此我们需要在石墩的位置选择一个合适的点,使得跳跃的次数最少。具体思路如下:

    1. 根据题目输入描述,获取小河的宽度L,石墩数N,每次最大跳跃距离M以及各个石墩到起点的距离列表。
    2. 初始化跳跃次数count为0,当前起点位置为0(即起点)。
    3. 循环遍历石墩列表,对于每个石墩的位置,判断是否超过了当前起点位置加上最大跳跃距离M,若超过则需要进行一次跳跃。
    4. 若石墩位置没有超过当前起点位置加上最大跳跃距离M,则将当前石墩位置设为新的起点位置。
    5. 重复步骤3~4,直到遍历完所有石墩。
    6. 输出跳跃次数count。

    下面是Python代码实现:

    def minimum_jumps(L, N, M, stones):
        count = 0
        current_pos = 0
    
        for stone in stones:
            if stone > current_pos + M:
                count += 1
                current_pos += M
            else:
                current_pos = stone
    
        return count
    
    # 获取输入
    L, N, M = map(int, input().split())
    stones = []
    for _ in range(N):
        stones.append(int(input()))
    
    # 调用函数并输出结果
    min_jumps = minimum_jumps(L, N, M, stones)
    print(min_jumps)
    

    该算法的时间复杂度为O(N),其中N为石墩数。由于石墩数的最大值为500,因此该算法在给定的数据范围内能够有效解决问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^