给定一个长度为n的区间:求m段连续子区间的和 最大值(其中m段子区间互不相交)
思路: dp[i][j]: 前j个元素i个连续区间最大值 (重要 a[j]必须在最后一个区间内)
转移方程:dp[i][j]=max (dp[i][j-1],dp[i-1][t]) + a[j] ( dp[i-1][t] 是 max ( dp[i-1[k] 1<=k<=j-1 )
第j个元素与第j-1个元素连在一起 ---》dp[i][j-1]
第j个元素单独一个区间 ----》dp[i-1][t]
重要: 1)如何优化
2)遍历推导的顺序 (想想为什么是 i在前 ,j在后)
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; const int N=1e6+3; const int INF=0x3f3f3f3f; int a[N],dp[N],pre[N]; int n,m; int main () { while (~scanf ("%d %d",&m,&n)) { memset (dp,0,sizeof(dp)); memset (pre,0,sizeof(pre)); for (int i=1;i<=n;i++) scanf ("%d",&a[i]); for (int i=1;i<=m;i++) { int _max=-INF; for (int j=i;j<=n;j++) { dp[j]=max (dp[j-1],pre[j-1])+a[j]; // dp[j] 前j个元素i段最大值 pre[j-1]=_max; // pre[j] 1~j 之中最大 dp[i-1][t] _max=max (_max,dp[j]); } } int ans=dp[m]; for (int i=m;i<=n;i++) // !!因为从i=1开始而导致的错误 ans=max (dp[i],ans); printf ("%d\n",ans); // !!可以直接 printf ("%d\n",_max); } return 0; }
抓住青春的尾巴。。。