题意:找出数列中最大子数列,如果有多个则输出第一个
分治法:对于一个数组a[low..high]:最大子数组a[i...j]必然所处的位置是一下三个情况之一:
1.完全位于子数组a[low..mid]中,因此low<=I<=j<=mid。
2.完全位于子数组a[mid+1...high]中,因此mid<I<=j<=high。
3.跨越了中点,因此low<=I<=mid<j<=high
对于一个数组a[low...high],求出跨越中点的最大子数组,分解为两个子数组:a[low..mid] a[mid+1..high] ,分别求出它们的最大子数组,去其中大的为a[low...high]的最大子数组;
#include<iostream>
#include<limits.h>
using namespace std;
const int N=100000;
int a[N];
struct array{
int left_max;
int right_max;
int sum;
array(int a,int b,int c){
left_max = a;
right_max =b;
sum = c;
};
array(){
left_max = 0;
right_max =0;
sum = 0;
};
};
array crossp(int *a,int low,int mid,int high)
{
int lmax=INT_MIN,rmax=INT_MIN;
int sum=0,lmaxpos=0,rmaxpos=0;
for(int i=mid;i>=low;i--)
{
sum+=a[i];
if(sum>=lmax)
{
lmax=sum;
lmaxpos = i;
}
}
sum=0;
for(int i=mid+1;i<=high;i++)
{
sum+=a[i];
if(sum>=rmax)
{
rmax=sum;
rmaxpos = i;
}
}
return array(lmaxpos,rmaxpos,lmax+rmax);
}
array find_max(int *a,int low,int high)
{
array l,r,m;
if(low==high)return array(low,high,a[low]);
else
{
int mid = (low+high)/2;
l = find_max(a,low,mid);
r = find_max(a,mid+1,high);
m = crossp(a,low,mid,high);
if(m.sum>=l.sum&&m.sum>=r.sum)return m;
else if(l.sum>=r.sum&&l.sum>=m.sum)return l;
else if(r.sum>=l.sum&&r.sum>=m.sum) return r;
}
}
int main()
{
int t,num;
cin>>t;
for(int i=0;i<t;i++)
{
cin>>num;
for(int i=0;i<num;i++)
cin>>a[i];
array c;
c = find_max(a,0,num-1);
cout<<"Case "<<i+1<<":"<<endl<<c.sum<<" "<<c.left_max+1<<" "<<c.right_max+1<<endl;
if(i!=t-1)cout<<endl;
}
}
做法二:动态规划
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define ll long long
using namespace std;
const int INF = ( 2e9 ) + 2;
const ll maxn = 100010;
int a[maxn];
int main()
{
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int sum=0,ans=0;
int l=1,r=1,x=1;
ans=sum=a[1];
for(int i=2;i<=n;i++)
{
if(sum+a[i]<a[i])
{
sum=a[i];
x=i;
}
else
sum+=a[i];
if(ans<sum) //更新答案
{
l=x;
r=i;
ans=sum;
}
}
if(cas!=1)puts("");
printf("Case %d:\n%d %d %d\n",cas,ans,l,r);
}
}