本題有三種作法,各位須要根據每一個題的數據範圍來決定本身用哪一種方法。spa
本題解中統一設最大和爲Max。code
咱們能夠枚舉它的子序列,也就是枚舉它的長度、起點和終點。咱們不妨設長度爲i,起點爲j,終點爲k,當前子序列的和爲s。因而咱們就有了下列核心代碼:blog
Max=a[1];//最大和初始化爲第一個數 for(i=1;i<=n;i++)//枚舉長度 for(j=i;j<=n;j++){//枚舉起點 s=0;//當前序列和初始化爲0 for(k=i;k<=j;k++)//枚舉終點 s+=a[k];//計算和 if(s>Max)Max=s;//比較 } printf("%d",Max);//輸出
這種方法在時限1s的題目中只能經過n<=450的範圍。class
可是本題的序列長度n<=200000。方法
因此採用該方法超時。總結
咱們能夠先求出從第一個數到當前數的和,而後枚舉起點和終點,計算每個子序列的和。因而咱們就有了下列核心代碼:數據
memset(s,0,sizeof(s));//初始化前綴和 for(i=1;i<=n;i++)s[i]=s[i-1]+a[i];//計算前綴和 Max=a[i];//初始化最大值爲第一個數 for(i=1;i<=n;i++) for(j=i;j<=n;j++) Max=max(Max,s[j]-s[i-1]);//枚舉起點和終點。 //注意是i-1!由於計算從第i個數開始的和須要減去前i-1個數的和 printf("%d",Max);
怎麼有點像DP?di
這種方法在時限1s的題目中只能勉強經過n<=10000的範圍。時間
可是本題的序列長度n<=200000。co
因此採用該方法也超時。
不妨設s爲以第i個數結尾的最大和,並每次計算和。
若當前和比最大值大,就更新最大值。
若當前和比0小,就把和清0。
核心代碼:
scanf("%d",&n); s=0; Max=-2e9; for(i=1;i<=n;i++){ scanf("%d",&a); s+=a; if(s>Max)Max=s; if(s<0)s=0; } printf("%d",Max);
這種方法在時限1s的題目中能勉強經過n<=100000000的範圍。
因爲本題的序列長度n<=200000。
因此能夠採用這種方法。
總結:必定要明白第三種方法的道理,而且能本身編寫代碼,這樣水平纔能有所提高。