题意;给你一个数组,让你找和最大的子序列,输出子序列的最大和,和子序列两端的位置。
由于这是我dp开始的第一题,我用了最淳朴的dp,结局当然是超时。
这是超时代码,但是我觉得这个代码真心体现了dp思想,可以给初学者了解dp用
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int a1[10005],dp[10005][10005];
int main()
{
int t,n,i,j,sum,a,b,k;
cin>>t;
for(k=1;k<=t;k++)
{
cin>>n;
sum=0;
for(i=1;i<=n;i++)
cin>>a1[i];
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(j==i+1) //可以自己画个二维坐标试 就明白了
dp[i][j]=a1[i]+a1[j];
if(dp[i][j]>sum)
{
sum=dp[i][j];
a=i;
b=j;
}
}
else
{
dp[i][j]=dp[i][j-1]+a1[j];
if(dp[i][j]>sum)
{
sum=dp[i][j];
a=i;
b=j;
}
}
}
}
printf("Case %d:\n",k);
printf("%d %d %d\n",sum,a,b);
}
}
然后就看看别人高大上的解法 自己写的 改了无数遍 最终AC
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 100010 //一开始超时 用了宏定义之后 就不超了
using namespace std;
int d[N],a1[N];
int main()
{
int t,n,Max,a,b,i,j,m;
scanf("%d",&t);
for(j=1;j<=t;j++)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a1[i]);
d[1]=a1[1];
Max=d[1]; //第一个数自己最大时的特殊情况
b=1;
for(i=2;i<=n;i++)
{
if(d[i-1]<0)
d[i]=a1[i];
else
d[i]=d[i-1]+a1[i];
if(Max<d[i])
{
Max=d[i];
b=i;
}
}
int f=0;
for(i=b;i>0;i--)
{
f+=a1[i];
if(f==Max)
a=i;
}
printf("Case %d:\n",j);
if(j!=t)
printf("%d %d %d\n\n",Max,a,b); //看清楚给的样例
else
printf("%d %d %d\n",Max,a,b);
}
}