P3009 [USACO11JAN] Profits S 题解复盘

P3009 USACO11JAN Profits S 题解复盘

模块:线性 DP

目标:求连续子数组的最大和(最大子段和)

基本信息

项目 内容
题目编号、来源 P3009 洛谷 / USACO11JAN Profits
训练层级 A 模板题
知识版块 线性 DP、最大子段和

解题前 · 关键信号识别

维度 分析
目标、约束、底层结构 目标 :求一个连续区间,使区间和最大。 约束 :必须是连续区间。 底层结构:当前位置的最优答案只依赖于前一个位置,因此属于线性 DP。
数据规模 N≤10^5,必须使用 O(n) 算法。
候选算法和依据 算法:线性 DP(最大子段和)。 依据:当前位置只有两种选择:重新开始一个新区间,或者接到前面的连续区间后面。
复杂度预判 时间复杂度 O(n),空间复杂度 O(n)(可优化为 O(1))。

解题后 · 外化复盘

维度 内容
实现结构 / 核心思路 定义 dp[i] 表示以第 i 个数结尾 的最大连续子段和。当前位置可以重新开始,也可以接在前面的连续区间之后,因此:dp[i]=max(v[i],dp[i-1]+v[i])。最后遍历 dp 取最大值即可。
错因回溯 1. 一开始误认为是区间 DP,实际上与区间合并没有关系。 2. ans 初始化成 0,导致全负数数据出错。 3. 没有意识到状态必须是"以 i 结尾",而不是任意区间。
边界和易错点 1. dp[1]=v[1]。 2. ans 初始化为 dp[1] 或一个极小值。 3. 全负数时答案仍然是最大的那个负数,而不是 0。
下次看到什么信号,我应该想到这个方法 看到"连续区间""最大和""最大利润""最大收益",立即想到:最大子段和(Kadane)+ 线性 DP。

AC 完整代码

cpp 复制代码
#include<iostream>
#include<algorithm>
using namespace std;

int dp[100005];

int main()
{
    int n;
    cin>>n;

    int v[100005];

    for(int i=1;i<=n;i++)
        cin>>v[i];

    dp[1]=v[1];
    int ans=dp[1];

    for(int i=2;i<=n;i++)
    {
        dp[i]=max(dp[i-1]+v[i],v[i]);
        ans=max(ans,dp[i]);
    }

    cout<<ans;

    return 0;
}

本题知识点总结

1. 状态定义

cpp 复制代码
dp[i]

表示:

以第 i 个元素结尾的最大连续子段和。


2. 状态转移

当前位置有两种选择:

重新开始:

cpp 复制代码
v[i]

或者:

接到前面的连续区间:

cpp 复制代码
dp[i-1]+v[i]

所以:

cpp 复制代码
dp[i]=max(v[i],dp[i-1]+v[i]);

3. 为什么必须是"以 i 结尾"?

因为只有这样:

下一状态:

cpp 复制代码
dp[i+1]

才能直接利用:

cpp 复制代码
dp[i]

如果状态定义成:

text 复制代码
前 i 个数中的最大子段和

就无法完成转移。


4. 为什么不是区间 DP?

区间 DP 一般具有:

text 复制代码
区间合并

例如:

cpp 复制代码
dp[l][r]

而最大子段和:

每个状态只依赖:

cpp 复制代码
dp[i-1]

属于:

text 复制代码
线性 DP

5. 空间优化

由于:

cpp 复制代码
dp[i]

只依赖:

cpp 复制代码
dp[i-1]

因此可以压缩成:

cpp 复制代码
int cur=v[1];

空间优化到:

text 复制代码
O(1)

一句话总结

看到"连续区间最大和",立即想到:dp[i] 表示以第 i 个元素结尾的最大连续子段和,转移:dp[i]=max(v[i],dp[i-1]+v[i])。

相关推荐
CQU_JIAKE1 天前
9.15【A】
算法·动态规划
yi0112 天前
DAY17: LeetCode 139|单词拆分:从“把单词删掉”到用 DP 记录合法切口
人工智能·笔记·python·算法·leetcode·动态规划
老歌老听老掉牙2 天前
动态规划:从递归到最优决策的算法艺术
算法·动态规划
richard_yuu4 天前
动态规划:强化学习的「数学基础」,从 MDP 到值迭代
深度学习·神经网络·算法·yolo·机器学习·动态规划
lvwangshu4 天前
P12960 毒药 题解
动态规划·题解·贪心·技巧·性质题·思维好题
彧azz12 天前
算法设计与分析:贪心与动态规划
数据结构·学习·算法·贪心算法·动态规划
Logic10113 天前
C语言/数据结构动态规划题解:Kadane算法求最大子数组和——O(n)时间O(1)空间
c语言·数据结构·动态规划·贪心·时间复杂度·算法题·最大子数组和
梦帮科技14 天前
AI 音乐产品的发布工程:验证门、数据发布、回滚与生产运维纪律
数据结构·数据库·架构·node.js·音视频·动态规划·推荐算法
语戚14 天前
力扣 1621. 大小为K的不重叠线段的数目:动态规划(Java 实现)
java·算法·leetcode·动态规划·力扣·dp
青山木14 天前
Hot 100 --- 最长有效括号
java·数据结构·算法·leetcode·动态规划