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

【题目链接】: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 -2
5
-8 3 2 0 5
8
6 -3 -2 7 -15 1 2 2
0
样例输出:
-1 0 0
10 1 4
8 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
****************************************************************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值