最大连续两段不相交字段和(poj2594,poj2479)

首先说一下连续字段和的求法

动态方程很容易推出b(i)=max(b(i-1),0)+a[i];定义b(i)为以i为结尾的最大连续和(注意这边是以i结尾,一定包含i,而如果我是求到第i个最大值还需要求出所有1~i的b(i)中的最大值)00000,最后再求出最大的b(i)

 l[0]=a[0];
 for (i=1;i<n;i++)
     {
         if (l[i-1]>0)
          l[i]=l[i-1]+num[i];
         else
           l[i]=num[i];
     }
注意这里l[i]保存的是到i为止(一定含有a[i]的连续和)而习惯上l[i]是1~i所以还要求出新的l[i]数组,即l[i]是不一定含有a[i]的
注意l[i]的更新要单独一个循环(坑啊,脑残了,写在里面错了多少次,因为你如果更新了l[i]就用到了更新过的数据l[i-1]也就是说l[i-1]是不一定含有a[i-1]


//poj2593注意要特判n==2因为必须至少要1个,比如1 -1只能输出0而不是1(注意这题貌似数据量小些,一开始错误写法都过了...)
#include <stdio.h>
#include <string.h>
int l[100005],r[100005];
int num[100005];
int max(int a,int b)
{
    return a>b?a:b;
}
 int main()
 {
     int i,j,n,ans;
     while((scanf("%d",&n)==1)&&n)
     {
     for (i=0;i<n;i++)
     scanf("%d",&num[i]);
     memset(l,0,sizeof(l));
     memset(r,0,sizeof(r));
     if (n==2)
     {
     printf("%d\n",num[0]+num[1]);
     continue;
     }
     l[0]=num[0];
     for (i=1;i<n;i++)
     {
         if (l[i-1]>0)
          l[i]=l[i-1]+num[i];
         else
           l[i]=num[i];
     }
     for (i=1;i<n;i++)
         if (l[i]<l[i-1])//注意i是以i结尾的最大连续和,即一定包含num[i],所以求1~i中的最大连续和时还需要找到之前的最大值
            l[i]=l[i-1];
      r[n-1]=num[n-1];
      for (i=n-2;i>=0;i--)
      {
          if (r[i+1]>0)
            r[i]=r[i+1]+num[i];
          else
            r[i]=num[i];
      }
      for (i=n-2;i>=0;i--)
        if (r[i]<r[i+1])
        r[i]=r[i+1];
     ans=0;
     for (i=0;i<n;i++)
        ans=max(ans,l[i]+r[i+1]);
     printf("%d\n",ans);
     }
     return 0;
 }

#include <stdio.h>
#include <string.h>
int l[50005],r[50005],num[50005];
int max(int a,int b)
{
    return a>b?a:b;
}
 int main()
 {
     int i,j,n,ans,T;
     scanf("%d",&T);
     while(T--)
     {
         scanf("%d",&n);
         memset(l,0,sizeof(l));
         memset(r,0,sizeof(r));
         memset(num,0,sizeof(num));
         ans=0;
         for (i=0;i<n;i++)
         scanf("%d",&num[i]);
          if (n==2)
         {
             printf("%d\n",num[0]+num[1]);
             continue;
         }
         l[0]=num[0];
         for (i=1;i<n;i++)
         {
             if (l[i-1]>0)
                l[i]=l[i-1]+num[i];
             else
                l[i]=num[i];
         }
         for (i=1;i<n;i++)
         if (l[i]<l[i-1])
         l[i]=l[i-1];
         r[n-1]=num[n-1];
         for (i=n-2;i>=0;i--)
         {
             if (r[i+1]>0)
                r[i]=r[i+1]+num[i];
             else
                r[i]=num[i];
         }
         for (i=n-2;i>=0;i--)
            if (r[i]<r[i+1])
             r[i]=r[i+1];
        for (i=0;i<n-1;i++)
         ans=max(ans,l[i]+r[i+1]);
         printf("%d\n",ans);
     }
     return 0;
 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值