题意:求的是给定n个数,求m个不相交的子段和的最大值.
dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][t])+a[j]);(i<=t<j)
代码写成f[j]=max(f[j-1],best[cur][j-1])+a[j]; //对应于下面的第一点
best[1-cur][j]=max(f[j],best[1-cur][j-1]);//第二点
dp[i][j]表示是前j个数据,i个子段并且包含a[j]的最大值,求dp[i][j]时分为两种情况.
1,前j-1个数据,i个字段并且包含a[j-1]的最大值,然后加上a[j],此时a[j]并入a[j-1]所在的段.
2.求出前j-1个数据中i个子段的最大值,注意这里的最大值与dp[i][j-1]是有区别的.不一定包含a[j-1],然后再加上a[j](单独作为一段).
最后在dp[m][j]中(m<=j<=n)找出最大值才是最后的结果
#include<iostream>
using namespace std;
int f[1000003];
int best[2][1000003];
int N, M;
int a[1000003];
int sum[1000003];
int main() {
while (scanf("%d%d", &M, &N) != EOF) {
int ans = -2000000000;
sum[0] = 0;
for (int i = 1; i <= N; i++) {
scanf("%d", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
for (int i = 0; i <= N; i++) best[0][i] = 0;
int cur = 0;
for (int j = 1; j <= M; j++) {
for (int i = 0; i <= j - 1; i++) best[1 - cur][i] = -2000000000;
for (int i = j; i <= N; i++) {
if (j == i) f[i] = sum[i];
else f[i] = max(best[cur][i - 1], f[i - 1]) + a[i];
best[1 - cur][i] = max(best[1 - cur][i - 1], f[i]);
if (j == M) ans = max(ans, f[i]);
}
cur = 1 - cur;
}
printf("%d\n", ans);
}
return 0;
}