最大子段和:给定一个序列(元素可正可负),找出其子序列中元素和最大的值。
我们用dp(i)表示序列中以元素ans(i)结尾的序列的最大子段和,那么有:dp(i)=max(dp(i-1)+ans(i),ans(i));
#define INF 999999999
int solve(int ans[],int n)
{
dp[0]=0;
int nmax=-INF;
for(int i=1;i<=n;i++)
{
dp[i]=max(dp[i-1]+ans[i],ans[i]);
nmax=max(nmax,dp[i]);
}
return nmax;
}
首先来看一道比较基础的最大子段和问题--HDU1003 Max Sum:
题目大意:给定一个序列,让求出此序列的最大子段和,并输出该子序列在原序列中的位置。
这里我们用变量sum来代替dp()数组,如果sum+a(i)<a(i),就更新sum的值,并重新纪录head的值,如果sum+a(i)>=a(i),则只需更新sum的值;
代码如下:
#include <cstdio>
#include <iostream>
using namespace std;
const int MAX=100005;
int main()
{
int t,n,a[MAX],i;
int T=0;
while(scanf("%d",&t)!=-1)
while(t--)
{
T++;
scanf("%d",&n);
int sum,max,head,tail,x;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
head=tail=x=1;
max=sum=a[1];
for(i=2;i<=n;i++)
{
if(sum+a[i]<a[i])
{
x=i;
sum=a[i];
}
else
{
sum+=a[i];
}
if(sum>max)
{
max=sum;
tail=i;
head=x;
}
}
printf("Case %d:\n%d %d %d\n",T,max,head,tail);
if(t) printf("\n");
}
return 0;
}
下面看POJ上一道最大子段和的问题 http://poj.org/problem?id=2479
题目大意:给你一个序列,求出这个序列中两个互不相交的子序列的和的最大值。
由于找两个互不相交的子序列,我们可以从左到右,再从右到左分别求出这个序列的dp()值,然后在这些dp()值互不重叠的情况下分别找出两个dp()的最大值相加即可。具体实现呢,可以简化这个思想,只需找出一个dp()值就可以,我们找出正序的dp()数组,对于逆序的情况呢,用一层for循环,每一次循环,我们用一个变量temp来存放从i到n的这些子序列中的最大子段和,然后和1到i的最大子段和相加,这样经历n次循环之后我们就找到了所要求的值。
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#define INF -999999999
using namespace std;
int ans[50050],dp[50050];
int main()
{
int t,n,i;
cin>>t;
while(t--)
{
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&ans[i]);
for(i=1;i<=n;i++)
dp[i]=max(dp[i-1]+ans[i],ans[i]);
int temp=0;
int solve=INF,nmax=INF;
for(i=n;i>1;i--)
{
temp=max(temp+ans[i],ans[i]);
nmax=max(nmax,temp);
if(solve<nmax+dp[i-1])
solve=nmax+dp[i-1];
}
printf("%d\n",solve);
}
return 0;
}
本文探讨了最大子段和问题,给出了如何找出序列中元素和最大的子序列的方法。通过动态规划(dp)策略,公式表示为:dp(i) = max(dp(i-1) + ans(i), ans(i))。文章以HDU1003和POJ2479两道题目为例,详细解释了解决这类问题的步骤。在HDU1003中,通过维护变量sum和记录起点head来更新最大子段和。而在POJ2479中,需要找到两个互不相交子序列的和的最大值,可以通过两次遍历分别计算正序和逆序的dp值来解决。"
131027869,10385585,Python升序排序:Lambda函数的秘密,"['Python', '算法', '编程技巧']
&spm=1001.2101.3001.5002&articleId=41698831&d=1&t=3&u=02851424dc5349bdb8399b20cc5dffe1)
6308

被折叠的 条评论
为什么被折叠?



