返回

贝茜的复仇:解开农夫约翰的数学难题

闲谈

引言

在 AcWing 1875 题中,农夫约翰给奶牛贝茜出了一道棘手的数学题,导致贝茜未能解决。为了报复,贝茜决定给约翰出一道更具挑战性的难题。本文将深入探讨贝茜的难题,提供分步指南和示例代码,帮助您征服这道难题。

难题概述

贝茜给约翰的难题是:

给定一个正整数序列 a_1, a_2, ..., a_n,请计算子序列和的最大值,其中子序列中的相邻元素之间的差值不超过 k。

分步指南

要解决此难题,我们可以遵循以下分步指南:

  1. 动态规划初始化: 创建一个二维数组 dp,其中 dp[i][j] 表示以元素 a_i 结尾且与 a_i 相差不大于 k 的子序列和的最大值。

  2. 递推关系: 对于每个元素 a_i,如果 a_i - a_j <= k,则 dp[i][j] = max(dp[i-1][j], dp[i-1][j-1] + a_i),其中 0 <= j <= i-1。

  3. 边界条件: 对于第一个元素 a_1,dp[1][0] = a_1。对于其他元素 a_i,dp[i][0] = max(dp[i-1][0], a_i)。

  4. 结果计算: 难题的答案是 max(dp[n][j]),其中 0 <= j <= n-1。

示例代码

C++代码:

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

int main() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 1);
    vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));

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

    dp[1][0] = a[1];
    for (int i = 2; i <= n; i++) {
        dp[i][0] = max(dp[i - 1][0], a[i]);
        for (int j = 1; j <= i; j++) {
            if (a[i] - a[j] <= k) {
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + a[i]);
            }
        }
    }

    int max_sum = 0;
    for (int j = 0; j <= n; j++) {
        max_sum = max(max_sum, dp[n][j]);
    }

    cout << max_sum << endl;
    return 0;
}

Java代码:

import java.util.Scanner;

public class BessiesRevenge {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int[] a = new int[n + 1];

        for (int i = 1; i <= n; i++) {
            a[i] = sc.nextInt();
        }

        int[][] dp = new int[n + 1][n + 1];
        dp[1][0] = a[1];

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

        int maxSum = 0;
        for (int j = 0; j <= n; j++) {
            maxSum = Math.max(maxSum, dp[n][j]);
        }

        System.out.println(maxSum);
    }
}

Python代码:

def bessies_revenge(n: int, k: int, a: list) -> int:
    """
    Calculates the maximum sum of a subsequence in the array 'a' such that the difference between adjacent elements is at most 'k'.

    Args:
        n (int): Length of the array 'a'.
        k (int): Maximum allowed difference between adjacent elements.
        a (list): Array of positive integers.

    Returns:
        int: Maximum sum of the subsequence.
    """
    dp = [[0 for _ in range(n + 1)] for _ in range(n + 1)]

    dp[1][0] = a[1]
    for i in range(2, n + 1):
        dp[i][0] = max(dp[i - 1][0], a[i])
        for j in range(1, i + 1):
            if a[i] - a[j] <= k:
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + a[i])

    max_sum = 0
    for j in range(0, n + 1):
        max_sum = max(max_sum, dp[n][j])

    return max_sum

结语

通过遵循分步指南和利用提供的示例代码,您可以轻松解决 AcWing 1875 中的贝茜难题。这不仅是一个解决数学难题的有趣挑战,而且还强调了动态规划技术在解决复杂计算问题中的重要性。