糖果吃法优化问题 | 豆包MarsCode AI刷题

99 阅读2分钟

问题描述

小R在接下来的n天里想要尽可能多地吃糖果。为了保持健康和节省零花钱,她规定如果今天吃了糖果,明天就不能吃。不过,小R允许自己有k次机会打破这个规则,在连续两天都吃糖果。她希望通过合理安排每天是否吃糖果,获得最大的糖果美味值。你的任务是帮助小R规划她的吃糖果方案,以使她吃到的糖果美味值最大。

输入

  • n:天数
  • k:允许打破规则的次数
  • a:一个长度为 n 的数组,表示每天糖果的美味值

输出

一个整数,表示小R能获得的最大美味值

解题思路

1. 动态规划

我们可以使用动态规划来解决这个问题。定义一个二维数组 dp,其中 dp[i][j] 表示在前 i 天中,使用 j 次打破规则的机会所能获得的最大美味值。

2. 状态转移
  • 今天不吃糖果dp[i][j] = dp[i - 1][j]
  • 今天吃糖果,昨天不吃dp[i][j] = max(dp[i][j], dp[i - 2][j] + a[i - 1])
  • 今天吃糖果,昨天也吃(使用一次机会)dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + a[i - 1])
3. 初始化
  • 当 i = 1 时,dp[1][j] = a[0],因为第一天无论如何都可以吃糖果。
4. 最终结果
  • 最终结果为 dp[n][k],即在前 n 天中,使用 k 次打破规则的机会所能获得的最大美味值。

数据结构

二维数组 dpdp[i][j] 表示在前 i 天中,使用 j 次打破规则的机会所能获得的最大美味值。

算法步骤

  1. 初始化 dp 数组。
  2. 遍历每一天和每次打破规则的机会。
  3. 根据状态转移方程更新 dp 数组。
  4. 返回 dp[n][k] 作为最终结果。

算法复杂度

  • 时间复杂度O(n * k),其中 n 是天数,k 是允许打破规则的次数。
  • 空间复杂度O(n * k),用于存储 dp 数组。

代码实现

int solution(int n, int k, vector<int> a) {
    // dp[i][j] 表示在前 i 天中,使用 j 次打破规则的机会所能获得的最大美味值
    vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));

    // 初始化边界条件
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j <= k; ++j) {
            // 今天不吃糖果
            dp[i][j] = dp[i - 1][j];

            // 今天吃糖果,昨天不吃
            if (i > 1) {
                dp[i][j] = max(dp[i][j], dp[i - 2][j] + a[i - 1]);
            } else {
                dp[i][j] = max(dp[i][j], a[i - 1]);
            }

            // 今天吃糖果,昨天也吃(使用一次机会)
            if (j > 0) {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + a[i - 1]);
            }
        }
    }

    // 返回最大美味值
    return dp[n][k];