杭电oj刷题——1003(最大连续子序列)
问题描述:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
Sample Input
2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5
Sample Output
Case 1:
14 1 4
Case 2:
7 1 6
#include<iostream>
using namespace std;
int main()
{
int thisSum, maxSum, t, temp, n, count = 0;
int maxLeft, maxRight, thisLeft;
cin >> t;
while(t--)
{
thisSum = 0;
cin >> n;
cin >> maxSum;
thisSum = maxSum;
maxLeft = maxRight = thisLeft = 0;
if(thisSum < 0)//注意事项
{
thisSum = 0;
thisLeft = 1;
}
for(int i = 1; i < n; i++)
{
cin >> temp;
thisSum += temp;
if(thisSum > maxSum)//步骤1
{
maxSum = thisSum;
maxLeft = thisLeft;
maxRight = i;
}
if(thisSum < 0)//步骤2
{
thisSum = 0;
thisLeft = i + 1;
}
}
cout << "Case " << ++count << ":" << endl;
cout << maxSum << " " << maxLeft + 1 << " " << maxRight + 1 << endl;
if(t != 0)
cout << endl;
}
return 0;
}
解题思路:该题所求的是总和最大的公共连续子序列,因此最简单的方法是暴力破解法,但是这种方法的时间复杂度过高,为n的三次方,因此不会AC。上述代码使用的方法是动态规划,在输入数据的过程中求解最大总和。
具体的方法:
1、使用thisSum和maxthis来记录当前总和和之前最大的总和,比较两者的大小,如果thisSum大于maxthis(即当前数是正数),则更新子序列的位置
2、如果thisSum的值小于0(也就是当前的负数的绝对值是大于之前所有值的总和),则要将thisSum清0,同时更新当前的位置。这样的目的是为了计算该负数之后的子序列的最大总和,以便和该负数之前的子序列总和比较,从而得出最大的子序列的总和。
注意:在输入第一个数据时也要看该数是否是负数,如果是则要按步骤2的方法进行处理。