洛谷P1115 最大子段和
法1
动态规划
分析:如果前面的子段加上第i个数是变大的就加上,如果变小则单独成为一个序列
状态表示:f[i]表示到i个数字位置的最大子段和的最大值
状态计算:f[i]分为包含第i个数的子段 和 自己重新开一个子段**
状态转移方程: f[i] = max(f[i - 1] + a[i], a[i])
贪心思想:对于可加可不加的数,不如加上。因为加上对答案没有坏处,而如果这个数后面还有一部分能让答案变多,因为本题求的子段是连续子段,不加上的话这两边就连不起来了。所以无脑加就行了。
- 第一个数为一个有效序列
- 如果一个数加上上一个有效序列得到的结果比这个数大,那么该数也属于这个有效序列。
- 如果一个数加上上一个有效序列得到的结果比这个数小,那么这个数单独成为一个新的有效序列
- 在执行上述处理的过程中实时更新当前有效序列的所有元素之和并取最大值。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2e5 + 10;
int n;
int f[N];
int a;
int ans = -1e9; //注意a的范围是-1e4,所以定义ans为比它小的,否则会出错
int main ()
{
cin >> n;
for(int i = 1; i <= n; i ++)
{
cin >> a;
f[i] = max(f[i - 1] + a, a);
ans = max(f[i], ans);
}
cout << ans << endl;
return 0;
}
法2
用s 来存 以前一个数为结尾子数组的和最大是多少
枚举输入的x
- s > 0 :s += x, s大于0则接上一定比不接更大
- s < 0 : s = x, s小于0则不接上一定比接上更大
- s = 0 :s为0,加不加都可以
3和2两类可以和为1类, s <= 0 , s = x;
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
int a;
int ans = -1e9;
int s;
int main ()
{
cin >> n;
for(int i = 1; i <= n; i ++)
{
cin >> a;
if(s < 0) s = 0;
s += a;
//等价于
// if(s >= 0) s += a;
// else s = a;
ans = max(ans, s);
}
cout << ans << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现