dp - 循环数组的最大和
首尾相连数组的最大子数组和
时间限制:1000 ms | 内存限制:65535 KB
难度:4
- 描述
- 给定一个由N个整数元素组成的数组arr,数组中有正数也有负数,这个数组不是一般的数组,其首尾是相连的。数组中一个或多个连续元素可以组成一个子数组,其中存在这样的子数组arr[i],…arr[n-1],arr[0],…,arr[j],现在请你这个ACM_Lover用一个最高效的方法帮忙找出所有连续子数组和的最大值(如果数组中的元素全部为负数,则最大和为0,即一个也没有选)。
- 输入
- 输入包含多个测试用例,每个测试用例共有两行,第一行是一个整数n(1=<n<=100000),表示数组的长度,第二行依次输入n个整数(整数绝对值不大于1000)。
- 输出
- 对于每个测试用例,请输出子数组和的最大值。
- 样例输入
-
6 1 -2 3 5 -1 2 5 6 -1 5 4 -7
- 样例输出
-
10 14
题目分析 :
首先想到的肯定是将数组扩大一倍, 将环变成链 , 但这里还有一个更巧妙的办法, 就是此题的最终结果一定是由着两种情况产生的, 一是 我不需要首尾相连,直接一个串过去就有最大值,二是我需要首尾相接,
想一想 , 它为什么需要首尾相接才有最大值? 不就是因为串的中间有一段最大 负串影响了第一种情况, 所以我可以求最大负串的和 。
代码示例:
/* * Author: ry * Created Time: 2017/9/19 8:09:07 * File Name: 1.cpp */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <stack> #include <queue> #include <set> #include <time.h> using namespace std; const int eps = 2e5+5; const double pi = acos(-1.0); #define Max(a,b) a>b?a:b #define Min(a,b) a>b?b:a #define ll long long int pre[eps]; int dp[eps]; int main() { int n; while(~scanf("%d", &n)){ int sum = 0; for(int i = 1; i <= n; i++){ scanf("%d", &pre[i]); sum += pre[i]; } memset(dp, 0, sizeof(dp)); int ans = 0; for(int i = 1; i <= n; i++){ dp[i] = max(dp[i-1]+pre[i], pre[i]); if (dp[i] > ans) ans = dp[i]; } int ans2 = 0; memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++){ dp[i] = min(dp[i-1]+pre[i], pre[i]); if (dp[i] < ans2) ans2 = dp[i]; } // if (ans > sum) printf("%d\n", sum); printf("%d\n", max(ans, sum-ans2)); } return 0; }
东北日出西边雨 道是无情却有情