4.1最大子数组问题
这类问题之前我都是用dp做的,通过刷新下标st与ed,来找到答案。
pst指的是可能的开头(possible start);
我的做法也是练习4.1-5的一个答案
pst=st=ed=1,maxsum=-inf,sum=0;
for(i=1;i<=n;i++)
{
sum+=a[i];
if(sum>=maxsum) st=pst,ed=i,maxsum=sum;
if(sum<=0) pst=i+1,sum=0;
}
printf("%lld\n",maxsum);
下面是分治法解决最大子数组问题的伪代码
长的我都不想啃QAQ
纯翻译代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn=1000000;
ll n,A[maxn],i;
ll findmax(ll A[],ll left,ll right)
{
ll MaxLeftSum,MaxRightSum;
ll MaxLeftBorderSum,MaxRightBorderSum;
ll LeftBorderSum,RightBorderSum;
if(left==right)
return A[left];
ll mid=(left+right)/2;
MaxLeftSum=findmax(A,left,mid);
MaxRightSum=findmax(A,mid+1,right);
MaxLeftBorderSum=LeftBorderSum=0;
for(i=mid;i>=left;i--)
{
LeftBorderSum+=A[i];
MaxLeftBorderSum=max(MaxLeftBorderSum,LeftBorderSum);
}
MaxRightBorderSum=RightBorderSum=0;
for(i=mid+1;i<=right;i++)
{
RightBorderSum+=A[i];
MaxRightBorderSum=max(MaxRightBorderSum,RightBorderSum);
}
return max(max(MaxLeftSum,MaxRightSum),max(MaxRightSum,MaxLeftBorderSum+MaxRightBorderSum));
}
int main()
{
scanf("%lld",&n);
for(i=1;i<=n;i++)
scanf("%lld",&A[i]);
printf("%lld\n",findmax(A,1,n));
return 0;
}
这题用代码实现难度还是挺大的QAQ
那个返回三个数把我卡了好久
算法解析:
mid=(st+ed)/2;
把所有子串分为三种,
case1.头尾都在st到mid
case2.头尾都在mid+1到ed
case3.头在st到mid,尾在mid+1到ed
答案就为max(case1,case2,case3)
case1,2,3继续递归,直到只剩一个元素