题目链接

小红的星尘收集

题目描述

小红在银河中发现了一个线性的星尘序列,每个位置的星尘都有固定的能量值 。小红可以收集星尘为飞船充能,但由于“量子纠缠”现象,如果收集了第 个位置的星尘,则相邻的第 个和第 个位置的星尘会消散。请帮小红计算在不违反规则的前提下,能收集到的最大能量总和。

输入:

  • 一行由若干个空格分隔的整数,代表序列中每团星尘的能量值

数据范围:

  • 星尘总数 满足:
  • 每个星尘的能量值 满足:

输出:

  • 一个整数,代表能收集到的最大能量总和。

解题思路

本题是一个经典的动态规划问题,即“不相邻子序列最大和”问题。

  1. 状态定义: 设 表示前 个星尘中能够收集到的最大能量总和。

  2. 状态转移方程: 对于第 个星尘(从 开始计数),有两种选择:

    • 不收集第 个星尘:此时最大能量等于前 个星尘的最大能量,即
    • 收集第 个星尘:此时不能收集第 个星尘,因此最大能量等于 加上前 个星尘的最大能量,即 。 综上所述:
  3. 初始化与边界情况

    • 根据数据范围 ,序列中至少有两个星尘。
  4. 复杂度分析

    • 时间复杂度:
    • 空间复杂度:,可以使用变量优化至

代码

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;

typedef long long LL;

int main() {
    string line;
    getline(cin, line);
    stringstream ss(line);
    vector<LL> a;
    LL val;
    while (ss >> val) {
        a.push_back(val);
    }

    int n = a.size();
    if (n == 1) {
        cout << a[0] << endl;
        return 0;
    }

    vector<LL> dp(n);
    dp[0] = a[0];
    dp[1] = max(a[0], a[1]);
    for (int i = 2; i < n; ++i) {
        dp[i] = max(dp[i - 1], a[i] + dp[i - 2]);
    }

    cout << dp[n - 1] << endl;
    return 0;
}
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        List<Long> a = new ArrayList<>();
        while (sc.hasNextLong()) {
            a.add(sc.nextLong());
        }

        int n = a.size();
        if (n == 1) {
            System.out.println(a.get(0));
            return;
        }

        long[] dp = new long[n];
        dp[0] = a.get(0);
        dp[1] = Math.max(a.get(0), a.get(1));
        for (int i = 2; i < n; i++) {
            dp[i] = Math.max(dp[i - 1], a.get(i) + dp[i - 2]);
        }

        System.out.println(dp[n - 1]);
    }
}
def solve():
    data = list(map(int, input().split()))

    n = len(data)
    if n == 1:
        print(data[0])
        return

    dp = [0] * n
    dp[0] = data[0]
    dp[1] = max(data[0], data[1])
    
    for i in range(2, n):
        dp[i] = max(dp[i - 1], data[i] + dp[i - 2])
        
    print(dp[n - 1])

if __name__ == "__main__":
    solve()

算法及复杂度

  • 算法:动态规划。
  • 时间复杂度: - 仅需一次遍历星尘序列。
  • 空间复杂度: - 使用了 数组存储中间状态。