题解——最大的和

解法一:分治思想

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,a[200200];
int fun(int l,int r)
{
  if(l==r) return a[l]; //递归终止的条件
  int mid=(l+r)/2; //int的截断让mid是准确的(偶数时偏左边那个)
  int maxm1=-222131231,maxm2=-21313123;
  int sum=0;
  /*注意这里循环不能是从1到mid,必须是mid到1,为了和后面第三种情况:
  最大和两端分布在中线的两边 ————maxm1+maxm2对应。*/
  for(int i=mid;i>=1;i--)//不断更新左侧数组中元素和的最大值
  {
    sum+=a[i];
    maxm1=max(sum,maxm1);
  }
  sum=0;
  for(int i=mid+1;i<=r;i++)//不断更新右侧数组中元素和的最大值
  {
    sum+=a[i];
    maxm2=max(sum,maxm2);
  }
  return max(max(fun(1,mid),fun(mid+1,r)),maxm1+maxm2);//开始递归
}
int main()
{
  int n;
  cin>>n;
  for(int i=0;i<=n;i++)
    cin>>a[i];
  cout<<fun(1,n);
  return 0;
}

解法二:(暴力模拟)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[200200];
int n;
int fun()//两次循环暴力计算
{
  int sum=0;
  int maxm=-213113;
  for(int j=1;j<=n;j++){ //(每一次就相当于从起点开始用了一次擂台法求“和”的最大值)
    for(int i=j;i<=n;i++){
      sum+=a[i];
      maxm=max(sum,maxm);//maxm在动态变化
    }  
    sum=0;
  }
  return maxm;
}
int main()
{
  cin>>n;
  for(int i=1;i<=n;i++)
    cin>>a[i];
  cout<<fun();
  return 0;
}

解法三:(贪心算法)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[200200];
int n;
int fun() //贪心算法(时间复杂度最低)
{
/* 原理在于:
如果前缀和sum变成了负数,那么下一个数就不需要前面的数了(因为还不如只选它一个)
如果前缀和sum没有成符数,就说明前面所有的前缀元素和是有贡献的,不能抛弃他们*/
  int sum=0;
  int maxm=-213113;
  for(int j=1;j<=n;j++)

  {

    sum+=a[j];
    if(sum<0)
      sum=0;
    maxm=max(sum,maxm);
  }
  return maxm;
}
int main()
{
  cin>>n;
  for(int i=1;i<=n;i++)
    cin>>a[i];
  cout<<fun();
  return 0;
//此题如果出现测试集全为负数的情况就需要开特例处理了
}

这篇文章,是又一个故事的结束...
lazy's story is continuing.
原文地址:https://www.cnblogs.com/Hello-world-hello-lazy/p/13526911.html