1007 Maximum Subsequence Sum (25分)
最大子段和
- 如果答案不唯一,输出索引较小的解。
- 如果所有数都为负数,输出0
解法一:贪心
若当前指针所指元素之前的和小于\(0\),则丢弃当前元素之前的数列。
const int N=10010;
int a[N];
int n;
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int sum=0;
int ans=-INF;
int st=0,ed=0;
int resl,resr;
for(int i=0;i<n;i++)
{
if(sum < 0) sum=a[i],st=i,ed=i;
else sum+=a[i],ed=i;
if(sum > ans)
{
ans=sum;
resl=st,resr=ed;
}
}
if(ans < 0) ans=0,resl=0,resr=n-1;
cout<<ans<<' '<<a[resl]<<' '<<a[resr]<<endl;
//system("pause");
return 0;
}
解法二:动态规划
状态表示:\(f(i)\):下标从\(0~i\),且以第\(i\)个数结尾的最大子段和
状态转移:要么与前面的相邻子数组连接,形成一个和更大的子数组;要么不与前面的子数组连接,自成一派,自己作为一个子数组。
\[f(i)=max(f(i-1)+a[i],a[i])
\]
注意:
- 不能将\(f(i)\)表示为:下标从\(0~i\)的最大子段和,否则无法转移
- 最后需要扫一遍\(f\)数组取最优值哦
const int N=10010;
int a[N];
int f[N];
int pre[N];
int n;
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
f[0]=a[0];
pre[0]=0;
for(int i=1;i<n;i++)
{
if(f[i-1]+a[i] >= a[i])
{
f[i]=f[i-1]+a[i];
pre[i]=pre[i-1];
}
else
{
f[i]=a[i];
pre[i]=i;
}
}
int index=0;
for(int i=0;i<n;i++)
{
if(f[index] < f[i])
index=i;
}
if(f[index] < 0)
cout<<0<<' '<<a[0]<<' '<<a[n-1]<<endl;
else
cout<<f[index]<<' '<<a[pre[index]]<<' '<<a[index]<<endl;
//system("pause");
return 0;
}