HDU 1024 Max Sum Plus Plus 简单DP
这题的意思就是取m个连续的区间,使它们的和最大,下面就是建立状态转移方程
dp[i][j]表示已经有 i 个区间,最后一个区间的末尾是a[j]
那么dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][1..j-1])+a[j])
看数据范围,1e6 肯定开不下数组,观察发现,dp[i][j]仅和dp[i][j-1]和dp[i-1][1..j-1]中最大值有关,即只和dp[i-1]有关
所以开滚动数组求解 复杂度可以通过开数组mmax[j]表示dp[i-1][1..j-1]中最大值,这个数组可以同时更新,这样复杂度降到O(mn)
然后,我觉得肯定是m比较小,要不然肯定也是超时啊QAQ......
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include <algorithm> #include<cstring> using namespace std; const int maxn=1000005; const int INF=0x7fffffff; typedef long long sum[maxn]; int a[maxn],dp[maxn],mmax[maxn]; int main() { int n,m; while(~scanf("%d%d",&m,&n)) { for(int i=1; i<=n; ++i) scanf("%d",&a[i]); int ans=-INF; memset(mmax,0,sizeof(mmax)); for(int i=1; i<=m; ++i) { int cc=-INF; ans=-INF; for(int j=i; j<=n; ++j) { dp[j]=max(dp[j-1]+a[j],mmax[j-1]+a[j]); mmax[j-1]=cc; cc=max(cc,dp[j]); } ans=max(ans,cc); } printf("%d\n",ans); } return 0; }