POJ 2749最大子段和 双向DP


Maximum sum
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 23327   Accepted: 7028

Description

Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:Your task is to calculate d(A).


Input

The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input.
Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.

Output

Print exactly one line for each test case. The line should contain the integer d(A).

Sample Input

1

10
1 -1 2 2 3 -3 4 -4 5 -5


双向DP,从左到右求最大子段和,再从右到左求最大子段和,再求dpl[i]+dpr[i+1]的最大值,


即求以num[i]结束的左边的最大子段和+以num[i+1]结束的右边的最大小段和的最大值



#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN=50000;
int num[MAXN+10];
int dpl[MAXN+10];
int dpr[MAXN+10];
int main()
{
  int t;
  int n;
  int i;
  scanf("%d",&t);
  while(t--)
    {
      scanf("%d",&n);
      for(i=0;i<n;i++)
	{
	  scanf("%d",&num[i]);
	}
      dpl[0]=num[0];
      for(i=1;i<n;i++)//from left to right,the max of sum of subsequence 
	{
	  //if(dpl[i-1]+a[i]>dpl[i-1])
	  if(dpl[i-1]>0)
	    {
	      dpl[i]=dpl[i-1]+num[i];
	    }
	  else  if(dpl[i-1]<=0)
	    {
	      dpl[i]=num[i];
	    }
	  // printf("%d ",dpl[i]);
	  
	}
      // cout<<endl;
      dpr[n-1]=num[n-1];
      for(i=n-2;i>=0;i--)//from right to left,the max of sum of subsequence 
	{
	  //if(dpr[i+1]+a[i]>dpr[i+1])
	  if(dpr[i+1]>0)
	    {
	      dpr[i]=dpr[i+1]+num[i];
	    }
	  else if(dpr[i+1]<=0)
	    {
	      dpr[i]=num[i];
	    }
	  //	  printf("%d ",dpr[i]);
	 
	}
      //      cout<<endl;
      int result=-100000000;
      for(i=n-2;i>=0;i--)
	{
	  if(dpr[i]<dpr[i+1])
	    {
	      dpr[i]=dpr[i+1];
	    }
	}
      for(i=0;i<n-1;i++)
	{
	  if(dpl[i]+dpr[i+1]>result)
	    {
	      result=dpl[i]+dpr[i+1];
	    }
	  
	  
	}
      printf("%d\n",result);
      
      
    }
  return 0;
}


你可能感兴趣的:(POJ 2749最大子段和 双向DP)