大学搞过两年的ACM,今天心血来潮的去杭电OJ上浏览了一下,真幸运账号居然没有记错。。然后想着之前学过很多经典的算法,但是很遗憾当时没有记录下来,所以现在弥补遗憾的时候到了,算法会不定期更新。
#include <stdio.h>
int array[100005],n;
void maxSubSum1();
void maxSubSum2();
void maxSubSum3();
int main(){
int t,i,num=0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&array[i]);
}
printf("Case %d:\n",++num);
//maxSubSum1(); //复杂度O(n^2),针对正整数
//maxSubSum2(); //复杂度O(n),针对正整数
maxSubSum3(); //复杂度O(n),针对正负整数
if(t){
printf("\n");
}
}
}
void maxSubSum1(){
int i,j,begin,end,max,sum;
begin=end=max=0;
for(i=0;i<n;i++)
{
sum=0;
for(j=i;j<n;j++)
{
sum+=array[j];
if(sum>max){
max=sum;
begin=i;
end=j;
}
}
}
printf("%d %d %d\n",max,begin+1,end+1 );
}
void maxSubSum2(){
int i,begin,end,max,sum;
begin=end=max=sum=0;
for(i=0;i<n;i++)
{
sum+=array[i];
if(sum>max){
max=sum;
end=i;
}
if(sum<0){
sum=0;
begin=(i+1)>n?n:i+1;
}
}
printf("%d %d %d\n",max,begin+1,end+1 );
}
void maxSubSum3(){
int i,begin,end,max,sum;
begin=end=0;
max=sum=array[0];
int dex=0; //保存改动的位置
for(i=1;i<n;i++)
{
if(sum+array[i]<array[i]){
sum=array[i];
dex=i;
}else{
sum+=array[i];
}
if(sum>max){
max=sum;
begin=dex;
end=i;
}
}
printf("%d %d %d\n",max,begin+1,end+1 );
}
首先,前面两个函数是针对正整数有效的,然后第三个函数是针对正负整数的,也就是能A掉HDU1003的做法。复杂度O(n^2)是暴力算法,没有什么好讲的,然后O(n)是DP思想,状态转移方程为
f[i]=max(f[i-1]+a[i],a[i])。