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 Input1
10
1 -1 2 2 3 -3 4 -4 5 -5Sample Output13Hint
In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer.
Huge input,scanf is recommended.
拿题思想:首先拿到这题时,我理解成了求一个数组中的元素和最大值,然后就想只需要将数组中的大于零的元素相加就可以咯。然而这是求一个数组中两个最大字段和,且两个字段没有重合的部分。之后就想如何求最大子段,应该是从第一个数开始验证,然后调用递归找出最大子段的元素和;最后将状态量设为名为dp的数组。
遇到的问题:再写的过程中遇到了运行时间的问题,由于审题不够严谨忽略了Huge input,scanf is recommended.这个问题,一直用的cin经行输入,导致超时,然后用scanf才ac的。
最终解题步骤:
1)定义三个全局变量,数组a储存输入的数据,dp1与dp2为所求最大子段过程中的状态量;
2)分别利用递归找出最大子段1,2;
3)用scanf进行输入操作,因为测试的数据很多;
#include <iostream>
#include <stdio.h>
using namespace std;
int a[50001],dp1[50001],dp2[50001]; //定义的三个全局变量,方便调用;
int main()
{
int t,n,sum,max;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
dp1[0]=-10001;
sum=0;
for(int i=1;i<=n;i++) //利用递归求第一个最大子段;
{
scanf("%d", &a[i]); //用scanf函数输入解决数据多的问题,防止用cin超时;
if(dp1[i-1]>a[i]+sum)
dp1[i]=dp1[i-1];
else dp1[i]=a[i]+sum;
sum+=a[i];
if(sum<0)
sum=0;
}
dp2[n+1]=-10001;
sum=0;
max=-10001;
for(int i=n;i>=0;i--) //利用递归求第二个最大子段;
{
if(dp2[i+1]>a[i]+sum)
dp2[i]=dp2[i+1];
else dp2[i]=a[i]+sum;
sum+=a[i];
if(sum<0)
sum=0;
if(dp1[i]+dp2[i+1]>max)
max=dp1[i]+dp2[i+1];
}
printf("%d\n", max);
}
return 0;
}
感想:这是我开始的第一道动态规划的题,发现了其中的难处,就是如何将问题用动态规划的形式进行处理?是这样先可以将问题用普通求解的方法先进性处理,然后再转化为动态规划的形式进行处理。最后加油!加油!