【剑指offer之最大子向量和(连续子数组的最大和)】

来源:互联网 发布:uiautomator java 编辑:程序博客网 时间:2024/05/16 01:01

【题目链接】:click here~~ 

【题目描述】:

题目1372:最大子向量和(连续子数组的最大和)

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:2987

解决:784

题目描述:

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天JOBDU测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?

输入:

输入有多组数据,每组测试数据包括两行。

第一行为一个整数n(0<=n<=100000),n=0,输入结束。接下去的一行包含n个整数(我们保证所有整数属于[-1000,1000])

输出:

对应每个测试案例,需要输出3个整数单独一行,分别表示连续子向量的最大和、该子向量的第一个元素的下标和最后一个元素的下标。若是存在多个子向量,则输出起始元素下标最小的那个。

样例输入:
3-1 -3 -25-8 3 2 0 586 -3 -2 7 -15 1 2 20
样例输出:
-1 0 010 1 48 0 3
【思路】:考虑DP,函数F(i)表示已第i个数字结尾的子数组的最大和,那么我们需要求出max(F[i]),其中0<=i<n。

我们得到如下递归公式:


             


公式的意义:当以第i-1个数字结尾的子数组中所有数字的和小于0时,如果把这个负数与第i个数相加,得到的结果比原先还小,所以这种情况以第i个数字结尾的子数组就是第i个数本身。如果以第i-1个数字结尾的子数组中所有数字的和大于0,与第i个数累加就得到以第i个数结尾的子数组中所有数字和。

对于记录开始与结束位置下标,我们知道,每当当前子数组和的小于0时,便是新一轮子数组的开始,每当更新最大和时,便对应可能的结束下标,这个时候,只要顺便用本轮的起始和结束位置更新始末位置就可以,程序结束,最大子数组和以及其始末位置便一起被记录下来了。

【代码】:

#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <set>#include <stack>#include <math.h>#include <map>#include <queue>#include <deque>#include <vector>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 1e5+10;const LL MOD = 999999997;const int inf= 0x3f3f3f3f;int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};/*Super waigua */inline int read(){    int  c=0,f=1;    char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}    return c*f;}int a[maxn];int max_sum_of_arr(int *a,int n){    int cur_begin=0,begin=0,end=0;    int sum=-inf;    int cur_sum=0;    for(int i=0; i<n; ++i)    {        if(cur_sum<0) {cur_sum=a[i];cur_begin=i;  }        else cur_sum+=a[i];        if(cur_sum>sum){sum=cur_sum;begin=cur_begin;end=i;}    }    printf("%d %d %d\n",sum,begin,end);}int main(){  //  freopen("in.txt","r",stdin);    int n,m;    while(~scanf("%d",&n)&&n)    {        for(int i=0; i<n; ++i) a[i]=read();        max_sum_of_arr(a,n);    }    return 0;}/**************************************************************    Problem: 1372    User: herongwei    Language: C++    Result: Accepted    Time:190 ms    Memory:1908 kb****************************************************************/


1 0