http://acm.hdu.edu.cn/showproblem.php?pid=1231
WA的代码,我还不知道WA在哪里。
#include<iostream>
using namespace std;
#include<string.h>
long long num[10005];
struct Node
{
int start,end;
long long sum;
}dp[10005];
int main()
{
int k;
while(scanf("%d",&k)!=EOF&&k)
{
int i;
for(i=1;i<=k;i++)
scanf("%lld",&num[i]);
for(i=0;i<=k;i++)
dp[i].sum=-0x3f3f3f;
for(i=1;i<=k;i++)
{
if(num[i]>dp[i-1].sum+num[i])
{
dp[i].start=i;
dp[i].end=i;
dp[i].sum=num[i];
}
else
{
dp[i].start=dp[i-1].start;
dp[i].end=i;
dp[i].sum=dp[i-1].sum+num[i];
}
}
dp[1].start=1;
long long Max=-0x3f3f3f;
int nnum=0;
for(i=1;i<=k;i++)
{
if(dp[i].sum>Max)
{
Max=dp[i].sum;
nnum=i;
}
}
if(Max<0)
{
printf("0 ");
printf("%d %d\n",num[1],num[k]);
}
else
printf("%lld %d %lld\n",dp[nnum].sum,num[dp[nnum].start],num[dp[nnum].end]);
/*long long sum=0;
long long Max=0;
for(i=0;i<k;i++)
{
sum+=num[i];
if(sum>=0)
Max=max(Max,sum);
else
sum=0;
}
printf("%lld\n",Max);*/
}
return 0;
}
最大连续子序列算是dp中比较简单的情况了吧,有的时候都不需要用到状态转移方程,比如这个题这种的,就是只求正的最大连续子序列,如果抛开需要输出这个最大子序列的头尾的话,就只需要设一个sum,一个max,如果sum>0,就加上新的,然后如果sum<0了,就无论如何sum都是一个“拖累”,所以sum变成num【i】,但是这样不能求负数的最大连续子序列。
其实dp状态方程应该是dp[i]=max(dp[i-1]+num[i],num[i]);这个状态转移方程我觉得是比较好理解的了,但是我最开始都没有想到,笨!
为了记录最大连续子序列的头跟尾,我又开了一个结构体,其实感觉不需要这么复杂的,因为在ACM中,感觉更好的方法不是保存,而是更新!
一会儿敲一份大神的代码上来!
#include<iostream>
using namespace std;
int num[10005],dp[10005];
int main()
{
int n,i,j,Max,cnt;
while(scanf("%d",&n)!=EOF&&n)
{
for(i=0;i<n;i++)
scanf("%d",&num[i]);
int left,right,flag;
Max=num[0];
cnt=0;
left=right=num[0];
for(i=0;i<n;i++)
{
if(cnt<0)
{
cnt=num[i];
flag=num[i];
}
else
cnt+=num[i];
if(cnt>Max)
{
Max=cnt;
left=flag;
right=num[i];
}
}
if(Max<0)
{
printf("0 %d %d\n",num[0],num[n-1]);
continue;
}
printf("%d %d %d\n",Max,left,right);
}
return 0;
}
☝我真的好喜欢这个大神的代码风格,简洁干净,特别好!虽然有的时候可能逻辑性比较强然后就看不懂什么的!