You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SPOJ TRT(奶牛零食售卖)问题DP解法及年龄处理技术咨询

零食售卖最大化收益的DP解法解析

嗨,作为DP初学者能写出递归思路已经很棒啦!你的递归逻辑完全正确,但确实存在大量重复计算的问题——比如同一个区间[x,y]会被多次调用计算,效率很低。咱们来一步步拆解这个问题的基础DP思路,重点解决年龄参数的处理问题。

核心DP状态定义

首先,我们不需要把年龄作为DP状态的一部分,因为年龄可以通过当前剩余零食的数量推导出来。

我们定义dp[x][y]表示:当盒子里剩下从第x个到第y个零食(闭区间,索引从0开始)时,能获得的最大收益。

那年龄怎么算呢?总共有N份零食,当剩下y-x+1份时,说明已经卖了N - (y-x+1)份,当前的售卖天数(年龄)就是 1 + (N - (y-x+1)) = N - (y-x+1) + 1,简化后是 N - y + x,或者也可以用区间长度计算:年龄 = N - 区间长度 + 1(区间长度是y-x+1)。

状态转移方程

对于区间[x,y],我们有两种选择:

  1. 从左端取零食x,当天收益是v[x] * 当前年龄,剩下的区间[x+1,y]的最大收益是dp[x+1][y],总收益为 v[x] * 年龄 + dp[x+1][y]
  2. 从右端取零食y,当天收益是v[y] * 当前年龄,剩下的区间[x,y-1]的最大收益是dp[x][y-1],总收益为 v[y] * 年龄 + dp[x][y-1]

所以状态转移方程就是:

dp[x][y] = max(
    v[x] * 年龄 + dp[x+1][y],
    v[y] * 年龄 + dp[x][y-1]
)

初始化与填充顺序

  • 初始化:当区间长度为1时(x==y),这是最后剩下的零食,会在第N天售卖,所以dp[x][x] = v[x] * N
  • 填充顺序:我们需要从短区间到长区间依次计算,因为长区间的结果依赖于更短的区间结果。比如先算所有长度为1的区间,再算长度为2的,直到长度为N的区间(也就是整个零食序列)。

示例验证(以题目输入为例)

题目输入:

5
1
3
1
5
2

对应的v = [1,3,1,5,2],N=5。

  • 长度为1的区间:dp[0][0]=1*5=5,dp[1][1]=3*5=15,dp[2][2]=1*5=5,dp[3][3]=5*5=25,dp[4][4]=2*5=10
  • 长度为2的区间,比如[0,1],年龄是5-2+1=4,收益为max(1*4+15, 3*4+5)=max(19,17)=19
  • 以此类推,最终计算到dp[0][4]时,结果就是43,和题目输出一致。

完整DP代码示例(自底向上)

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

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

    // 创建DP矩阵,dp[x][y]表示区间[x,y]的最大收益
    vector<vector<int>> dp(N, vector<int>(N, 0));

    // 初始化长度为1的区间
    for (int i = 0; i < N; ++i) {
        dp[i][i] = v[i] * N;
    }

    // 枚举区间长度从2到N
    for (int len = 2; len <= N; ++len) {
        for (int x = 0; x + len <= N; ++x) {
            int y = x + len - 1;
            int age = N - len + 1; // 当前售卖的天数
            dp[x][y] = max(
                v[x] * age + dp[x+1][y],
                v[y] * age + dp[x][y-1]
            );
        }
    }

    cout << dp[0][N-1] << endl;
    return 0;
}

为什么不用把年龄放进状态?

如果把年龄作为状态的一部分,DP会变成三维(dp[x][y][age]),空间和时间复杂度都会飙升到O(N³),对于N=2000来说完全不可行。而通过推导把年龄转化为x和y的表达式,就能把状态压缩到二维,时间复杂度降到O(N²),对于N=2000来说,400万次计算完全在合理范围内。

内容的提问来源于stack exchange,提问作者RAHUL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:50:20