最大子段和 (HDU1231)
题目就是给你一个序列,你找到其中和最大的子序列。
这是最基础的DP:
dp[i] 表示当最大子序列包括a[i]时最大子段和。如果dp[i-1] < 0 那么dp[i] = a[i] ,否则dp[i] = dp[i-1] + a[i]。
#include<cstdio>
using namespace std;
const int SIZE = 10005;
int N;
int A[SIZE];
int dp[SIZE];
int main()
{
while(scanf("%d",&N)!=EOF && N)
{
for(int i=1;i<=N;i++) scanf("%d",&A[i]);
int res = -1;
int temp = -1;
dp[0] = -1; // 防止第0个元素被选中
int fr = 1, en = N;
for(int i=1;i<=N;i++)
{
if(dp[i-1] < 0)
{
dp[i] = A[i];
temp = i;
if(dp[i] > res)
{
res = dp[i];
fr = i;
en = i;
}
}
else
{
dp[i] = dp[i-1] + A[i];
if(dp[i] > res)
{
res = dp[i];
fr = temp;
en = i;
}
}
}
if(res < 0) res = 0;
printf("%d %d %d\n",res,A[fr],A[en]);
}
return 0;
}
最大M子段和:HDU1024
搞了很久发现是自己理解错题意
dp[j] 以j个元素结尾的最大i子段和
maxdp[j] 到j为止最大i-1子段和
j from i tp N
dp[j] = max(dp[j-1], maxdp[j-1]) + A[i]
maxdp[j-1] = max(dp[k]) (k from 1 to j-1)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int SIZE = 1000005;
typedef long long ll;
int N,M;
ll dp[SIZE];
ll maxdp[SIZE];
ll A[SIZE];
ll maxx(ll a,ll b)
{
if(a < b) return b;
return a;
}
int main()
{
while(scanf("%d %d",&M,&N)!=EOF)
{
for(int i=1;i<=N;i++) scanf("%I64d",&A[i]);
fill(maxdp,maxdp+1+N,0);
fill(dp,dp+1+N,0);
//printf("dp[0]=%I64d\n",dp[0][1]);
long long temp;
for(int i=1;i<=M;i++)
{
temp = -0x7fffffff;
for(int j=i;j<=N;j++)
{
dp[j] = maxx(dp[j-1],maxdp[j-1]) + A[j];
maxdp[j-1] = temp;
temp = maxx(temp,dp[j]);
}
}
printf("%I64d\n",temp);
}
}