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])

相关推荐
find1star10 小时前
LeetCode 25:K 个一组翻转链表
java·数据结构·算法·leetcode·链表·职场和发展·动态规划
chushiyunen11 小时前
动态规划、贪心算法、分治法
算法·贪心算法·动态规划
梓䈑1 天前
【动态规划系列】路径问题、子数组 和 子序列问题、背包问题
c++·算法·动态规划
微功夫信息技术2 天前
分层多智能体强化学习驱动的非急救转运公平 - 效率统一调度系统研究与实践
人工智能·学习·算法·动态规划
辰烨chenye3 天前
LeetCode Hot 100 题解 · 动态规划篇
算法·leetcode·动态规划
a187927218314 天前
【算法】动态规划第四篇:背包收官——min 哨兵、计数世界与组合排列分水岭
算法·leetcode·动态规划·dp·01背包·算法讲解·决策合并
a187927218314 天前
【算法】动态规划第三篇:背包第一课——贪心之死与正序倒序开关
算法·leetcode·动态规划·贪心·dp·暴力·算法讲解
a187927218314 天前
【算法】动态规划第五篇:区间 DP——从“看什么都像背包“到“最后戳谁“
算法·leetcode·动态规划·dp·区间·区间dp·算法讲解
rannn_1114 天前
【力扣hot100】多维动态规划|62、64、5、1143、72
算法·leetcode·动态规划
a187927218315 天前
【算法】动态规划第二篇:双序列 DP 三课——继承、计步与断链
算法·leetcode·动态规划·dp·回溯·暴力·算法讲解