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;
}
posted @ 2021-01-02 20:46  Dazzling!  阅读(50)  评论(0编辑  收藏  举报