HDU1003

这个题目WR了N多次。。一开始看见100000的输入想采用O(n2)的算法。。直接TLE了。。

今后估计这样太的数据应该采取O(n)或O(nlogn)的算法的。

原题:http://acm.hdu.edu.cn/showproblem.php?pid=1003

因为数据结构书上第一个算法分析实例就是这个题,也没怎么仔细看就直接写了,结果老WR,结果才发现书上的只针对Maxsum为正数的时候才适用,负数的时候书上为0,主要题目貌似也没怎么交代清楚,一个不加算不算子序列。不过AC以后才知道不算。

一开始采用O(nlogn)的分治算法觉得Maxsum很好求,但就是位置不好标记,因为最后涉及到合并,位置好像要讨论多次。就直接采用O(n)的算法。google一下,原来这就是一个很简单的DP思想。状态转移方程为f[i]=max(f[i-1]+a[i],a[i])。

代码:

#include<stdio.h>
int a[100010];
int main(){
	int case_number,k=0,i,number,position1,end,thissum,maxsum,begin;
	scanf("%d",&case_number);
	while(case_number--){
		k++;
		scanf("%d",&number);
		for(i=0;i<number;i++)
			scanf("%d",&a[i]);
		position1=begin=end=0;
		maxsum=thissum=a[0];
		for(i=1;i<number;i++){
			if(thissum+a[i]<a[i]){             //如果当前值比a[i]小的话则改为a[i]
				thissum=a[i];
				position1=i;                  //记录下改的位置
			}
			else{
				thissum=thissum+a[i];          
			}
			if(thissum>maxsum){                //当前值比最大值大,则头尾都要改
				maxsum=thissum;
				begin=position1;
				end=i;
			}
		}
		printf("Case %d:\n%d %d %d\n",k,maxsum,begin+1,end+1);
		if(case_number)                        //测试数据之后有空行,一开始也没看见,也WR了。
			printf("\n");
	}
	return 0;
}

在付上一个O(nlogn)的算法    分治法

//O(nlogn)   分治排序算法
int maxsum_version_1(int *a,int x,int y){  //求区间[x,y)的最大值     [2,3)为a2;
	int L,R,v,m,i,max;
	if(y-x==1)
		return a[x];
	m=x+(y-x)/2;                 //不取m=(y-x)/2 是为了使分界点靠近区间左端点
	max=(maxsum_version_1(a,x,m)>maxsum_version_1(a,m,y))?maxsum_version_1(a,x,m):maxsum_version_1(a,m,y);
	v=0;
	L=a[m-1];
	for(i=m-1;i>=x;i--){
		v=v+a[i];
		L=L>v?L:v;
	}
	R=a[m];
	v=0;
	for(i=m;i<y;i++){
		v+=a[i];
		R=R>v?R:v;
	}
	return (max>L+R)?max:L+R;
}

你可能感兴趣的:(数据结构,算法,Google,测试,n2)