循环数组求最大子段和系列-----------方法1

Equator
Time Limit: 2000ms, Special Time Limit:5000ms,Memory Limit:65536KB
Total submit users: 12, Accepted users:8
Problem 13248 : No special judgement
Problem description

In a galaxy far away, the planet Equator is under attack! The evil gang Galatic Criminal People Cooperation is planning robberies in Equator’s cities. Your help is needed! In order to complete your training for becoming a lord of the dark side you should help them deciding which cities to rob. As the name says, the desert planet Equator only can be inhabited on its equator. So the gang lands there at some point and travels into some direction robbing all cities on their way until leaving the planet again.

But what is still open for them is to decide where to land, which direction to take, and when to leave. Maybe they shouldn’t even enter the planet at all? They do not consider costs for traveling or for running their ship, those are peanuts compared to the money made by robbery!

The cities differ in value: some are richer, some are poorer, some have better safety functions. So the gang assigned expected profits or losses to the cities. Help them deciding where to begin and where to end their robbery to maximize the money in total when robbing every city in between.

Input

Output

For each test case print one integer describing the maximum money they can make in total.

Sample Input
3
3 1 2 3
8 4 5 -1 -1 1 -1 -1 5
2 -1 -1
Sample Output
6
14
0


      该题就是典型的求循环数组中最大子段和的问题!当然要暴力解决就可以直接写两个for循环,不过当然也肯定过不了再见,超时!!所以就需要想一下其他方法。在专题第一讲中我们知道了怎么求普通数组中最大子段和的问题,我们想一下是不是循环数组可以和普通数组挂钩呢??

      其实循环数组中最大值也可能是普通数组中的最大值,还有可能是数组首尾相连后的部分出现最大值。那么第一种情况我们当然会解决,但是后者呢??

      可以想一下为什么会出现后者这种情况。不难想到,之所以会出现后者是因为普通数组中有一段连续的和为负数,并且绝对值比较大,以至于影响到普通数组首尾相连后最大子段数发生改变。所以我们只需要把原来数组中的数全部取相反数再由普通数组方法求出最大子段数的和就是原来数组中连续负数的绝对值max2;当然一开始要求出普通数组中最大子段和max1,和总和sum。比较max1和sum+max2,就可以得到答案。

      代码如下:

<span style="font-size:18px;">#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define max(a,b)  ((a)>(b)?(a):(b))
#define MAXN 1000005

int a[MAXN];
int max_sum(int a[],int n);
int main()
{   int n,i,t;
    cin>>t;
    while(t--)
    {  int sum=0;
       cin>>n;
       for(i=0;i<n;i++)
       {   cin>>a[i];
           sum+=a[i];
       }
       int max1=max_sum(a,n);
       for(i=0;i<n;i++)
           a[i]=-a[i];
       int max2=max_sum(a,n);
       cout<<max(max1,sum+max2)<<endl;
    }
}
int max_sum(int a[],int n)
{   int sub_array=0;
    int i,sum=0;
    for(i=0;i<n;i++)
    {   if(sum>=0)
            sum+=a[i];
        else
            sum=a[i];
        if(sub_array<sum)
            sub_array=sum;
    }
    return sub_array;
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值