Luogu P1115 最大子段和(dp 贪心)

 P1115 最大子段和

题目描述

给出一段序列,选出其中连续且非空的一段使得这段和最大。

输入输出格式

输入格式:

输入文件maxsum1.in的第一行是一个正整数N,表示了序列的长度。

第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列。

输出格式:

输入文件maxsum1.out仅包括1个整数,为最大的子段和是多少。子段的最小长度为1。

输入输出样例

输入样例#1:
7
2 -4 3 -1 2 -4 3
输出样例#1:
4

说明

【样例说明】2 -4 3 -1 2 -4 3

【数据规模与约定】

对于40%的数据,有N ≤ 2000。

对于100%的数据,有N ≤ 200000。

  可以看出来是一道dp题,转移方程很好找, f[i] = max(f[i-1], 0) + a[i]

  边界条件是f[0] = 0            为什么要和0作比较,因为如果比0小,那么这个字段和活着也是挺失败的,不如重修2333

  AC①: dp(48ms)

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 int a[200005];
 5 int f[200005];
 6 
 7 int main()
 8 {
 9     int n;
10     scanf("%d", &n);
11     for(int i=1; i<=n; i++)
12         scanf("%d", &a[i]);
13     
14     for(int i=1; i<=n; i++)
15         f[i] = std::max(f[i-1], 0) + a[i];
16     
17     int maxx = -1234567;
18     for(int i=1; i<=n; i++)
19             if(f[i] > maxx)
20                 maxx = f[i];
21     
22     printf("%d", maxx);
23     return 0;
24 }

  还可以用贪心的思路做

  AC②: (贪心 36ms)

 1 #include <cstdio>
 2 
 3 int main()
 4 {
 5     int n, a, b, maxx;
 6     scanf("%d", &n);
 7     b = maxx = -1234567;    // b表示前几个字段和最大值
 8     for(int i=1; i<=n; i++)
 9     {
10         scanf("%d", &a);
11         if(b < 0)    b = a;    // 如果b<0 那么不如直接重开
12         else b += a;    // b>=0 说明前面的字段和比较大 可以继续加下去
13         if(b > maxx) maxx = b;
14     }
15     printf("%d", maxx);
16     return 0;
17 }
原文地址:https://www.cnblogs.com/yBaka/p/7397260.html