nefuoj1206-dp-环形子段和

来源:互联网 发布:课时优化八上英语答案 编辑:程序博客网 时间:2024/05/17 01:42

http://222.27.161.197/JudgeOnline/problemShow.php?problem_id=1206
说dp有点牵强。
中文题意
一个数组,有正有负。n个数组成一个环形,问你最大和是多少。
分两种情况
1 最大子段和不经过首尾。那么就直接算。
2 最大子段和经过首尾。那么咋算呢,可以想见的是最大子段和肯定和最小子段和 是不会发生重叠的(既然已经有最大子段和了,说明肯定有负数,那么最大子段和就是最长(并非qwq。。)最大的那个了,)
最大子段和里的负数肯定在里面。外面是正数
最小的肯定 正数在里面,负数在外面
否则没有。
这是可以求一下 最小子段和。减去的剩下那一段就是最大的了。
( 样例
6
7 2 -9 6 -5 -10
) 若最长子段 不要6,那么最短的肯定会要。就是酱紫

#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;const int maxn=50005;int main(){   int m;    int a[maxn];   while(~scanf("%d",&m))   {   for(int i=0;i<m;i++){           scanf("%lld",&a[i]);       }       long long sum1=0;       long long sum2=0;       long long ans1=0;       long long ans2=0;       long long all=0;       for(int i=0;i<m;i++){           sum1+=a[i];           all+=a[i];            if(sum1<0)            {  sum1=0;            }            if(sum1>ans1){                ans1=sum1;             }             sum2+=-a[i];             if(sum2<0){                sum2=0;             }             if(sum2>ans2){                ans2=sum2;             }       }       cout<<ans1<<endl;       cout<<all<<endl;       cout<<ans2<<endl;       if(ans1>all+ans2)        printf("%lld\n",ans1);       else        printf("%lld\n",all+ans2);   }    return 0;}
原创粉丝点击