题目
N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。
例如:-2 11 -4 13 -5 6 -2,分为2段,11 -4 13一段,6一段,和为26。
思路
f[i][j]: 前i段 使用前j个数字的最大值,一定要使用第j个值
g[i][j]: 前i段 使用前j个数字的最大值
f[i][j] = max(g[i - 1][j - 1] + val[j],f[i][j - 1] + val[j]);
g[i][j] max(f[i][j],g[i][j - 1]);
解
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
typedef long long ll;
typedef long long ll;
const int MAXN = 5010;
int val[MAXN];
int n,m;
ll f[2][MAXN];
ll g[2][MAXN];
int main() {
while (scanf("%d%d",&m,&n) != EOF) {
for (int i = 1; i <= m; i ++) {
scanf("%d",&val[i]);
}
for (int i = 0;i <= 1;i ++) {
for (int j = 0;j <= m;j ++) {
f[i][j] = g[i][j] = -0x3f3f3f3f3f3f3f3f;
}
}
g[0][0] = 0;
for (int i = 0;i <= m;i ++) {
g[0][i] = f[0][i] = 0;
}
for (int i = 1;i <= n;i ++) {
for (int j = 1;j <= m;j ++) {
f[i & 1][j] = max(g[(i - 1) & 1][j - 1] + val[j],f[i & 1][j - 1] + val[j]);
g[i & 1][j] = max(f[i & 1][j],g[i & 1][j - 1]);
}
}
cout << g[n & 1][m] << endl;
}
}