题目链接

小红的地砖

题目描述

小红正在进行一次体能训练,场地上依次铺设了 块地砖,按照从 依次编号。她站在第 块地砖上,目标是走到第 块地砖。 已知走到第 块地砖需要消耗 的体力值。每一次移动,小红可以选择:

  • 向前走 步,即从当前地砖 走到地砖
  • 向前走 步,即从当前地砖 走到地砖 。 请你帮助小红计算,从第 块地砖走到第 块地砖所需消耗的最小体力值。

解题思路

这是一个经典的动态规划问题。

我们定义 为到达第 块地砖时所消耗的最小体力值。我们的目标是求

要到达第 块地砖(当 时),只可能从以下两个位置跳过来:

  1. 从第 块地砖走 步。此时的体力消耗为
  2. 从第 块地砖走 步。此时的体力消耗为

为了使得到达第 块地砖的总体力消耗最小,我们应该选择从之前两块地砖中消耗较小的那一个跳过来。由此,我们可以得到状态转移方程:

接下来确定初始状态(边界条件):

  • :到达第 块地砖的消耗就是它自身的体力值。
  • :要到达第 块地砖,必须从第 块跳过来,所以总消耗是前两块地砖的体力值之和。

在实现时,我们注意到计算 只需要 的值。因此,没有必要用一个数组来存储所有的 值,只需用两个变量滚动地记录前两项即可。这样可以将空间复杂度从 优化到

代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    if (n == 1) {
        cout << a[0] << "\n";
        return 0;
    }

    // prev 对应 dp[i-2],curr 对应 dp[i-1]
    long long prev = a[0];
    long long curr = a[0] + a[1];

    for (int i = 2; i < n; i++) {
        long long next = min(prev, curr) + a[i];
        prev = curr;
        curr = next;
    }

    cout << curr << "\n";

    return 0;
}
import java.util.Scanner;
import java.lang.Math;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }

        if (n == 1) {
            System.out.println(a[0]);
            return;
        }

        // prev 对应 dp[i-2],curr 对应 dp[i-1]
        long prev = a[0];
        long curr = a[0] + a[1];

        for (int i = 2; i < n; i++) {
            long next = Math.min(prev, curr) + a[i];
            prev = curr;
            curr = next;
        }

        System.out.println(curr);
    }
}
n = int(input())
a = list(map(int, input().split()))

if n == 1:
    print(a[0])
else:
    # prev 对应 dp[i-2],curr 对应 dp[i-1]
    prev = a[0]
    curr = a[0] + a[1]

    for i in range(2, n):
        # 滚动更新
        prev, curr = curr, min(prev, curr) + a[i]
    
    print(curr)

算法及复杂度

  • 算法:动态规划
  • 时间复杂度:,我们需要一次循环遍历所有地砖。
  • 空间复杂度:,我们只使用了常数个变量来存储状态。