1. 程式人生 > >循環序列_最大子段和變種

循環序列_最大子段和變種

cst 而已 成了 div 比較 大連 方式 urn 最大連續

第一次寫博客.... 一道icpc選拔賽的水題.. 題目大意:給你一個整數的循環序列,也就是頭尾相接的序列,要求找出最大的一段子段和(循環意義下的) 也就是常求的最大子段和問題,只不過這次數組頭尾相接了而已

思路1:通常的方法就是復制這個整數數組接到原數組的後面,這樣就變成了求有上下限的最大子段和問題,解題方法自己去查閱相關資料。

思路2:我們可以換另外一種方式來想,求最大字段和,可以先通過ans-最小子段來解出循環意義下的最大子段和,而這個最小子段就是除去首尾元素之外的最小連續子段(這樣就達到了循環的意義),另外還是用最大子段和求出另外一種情況,這樣兩者相比較,最大者就是循環序列的最大子段和。

上我的代碼: #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100005],n;
int maxsum()//正常求最大連續子段和
{
int res,tmp;
res=tmp=a[0];
for(int j=1;j<n;j++)
{
if(tmp<0)
tmp=a[j];
else
tmp+=a[j];

res=max(res,tmp);
}
return res;

} int minsum()
{
if(n<=2)
return 0;//如果數組元素個數小於2就直接返回

int res,tmp;
res=tmp=a[1];
//除去首尾結點 找出其中的最小子段和 否則意義就和maxsum相同了
for(int j=2;j<n-1;j++)
{
if(tmp>0)
tmp=a[j];
else
tmp+=a[j];

res=min(res,tmp);
}

return res;
}
int main()
{
int tt=0,ans;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
tt+=a[i];}

/*int k1=maxsum();
int k2=minsum();
printf("**%d %d\n",k1,k2);*/

ans=max(maxsum(),tt-minsum());
printf("%d\n",ans);
return 0;

}

循環序列_最大子段和變種