1. 程式人生 > >dp - 循環數組的最大和

dp - 循環數組的最大和

stream lov sca 長度 spa 時間限制 cto 多個 難度

首尾相連數組的最大子數組和

時間限制: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;
}


dp - 循環數組的最大和