HDU1024 Max Sum Plus Plus
题意
给n个数,求取出m段(连续),最大和为多少
分析
错解:一开始考虑进去连续取这个条件,写了错的转移
定义:dp[i][j]:前 j 个数取出 i 段的最大和
决策:第 j 个数是和 j-1 一组, 还是单独成组
转移:dp[i][j] = max( dp[i][j-1] + a[j],dp[i-1][k] + a[j] ) ( i-1 <= k <= j-1)
直接写的时间复杂度(m*n^2)显然超时,从状态转移方程可以看出dp[i][j] 需要上一层 i-1 中 k ( i-1 <= k <= j-1)这些中最大值,开一个数组记录一下就好,这个数组用了一个小技巧“ 滞后 ”传递
优化:由于我们已经记录下了dp[i-1][k] ( i-1 <= k <= j-1)的最大值,所以直接一个一维数组即可
边界处理:直接让dp数组为0即可
时间复杂度O(m*n)
#include<stdio.h> #include<algorithm> #include<iostream> using namespace std; #define MAXN 1000000 #define INF 0x7fffffff int dp[MAXN+10]; int mmax[MAXN+10]; int a[MAXN+10]; int main() { int n,m; int i,j,mmmax; while(scanf("%d%d",&m,&n)!=EOF) { for(i=1;i<=n;i++) { scanf("%d",&a[i]); mmax[i]=0; dp[i]=0; } dp[0]=0; mmax[0]=0; for(i=1;i<=m;i++) { mmmax=-INF; for(j=i;j<=n;j++) { dp[j]=max(dp[j-1]+a[j],mmax[j-1]+a[j]); mmax[j-1]=mmmax; mmmax=max(mmmax,dp[j]); } } printf("%d ",mmmax); } return 0; }