题意 : 这个题目就是问你你一串数字分成 m 段连续和 问你 最大的划分是怎样的 输出这个划分和。
题解 : 如果不计时间复杂度 和 空间复杂度的话我们不难设计出一个动态规划的方程就是
dp (i,j,k) 表示前 i 个分成 j 段 k 取 0 / 1 表示第i个数选没选
那么转移的方程为
dp (i,j,0) = max (dp(i - 1,j,0),dp[i - 1,j,1));
dp (i,j,1) = max (dp(i - 1,j - 1,0),dp (i - 1,j - 1,1)) + a (i);
可惜这么做会爆内存,所以我门不难想到滚动数组,然后就写一个滚动数组就好了
别忘记边界
dp (0,0) = 0;
这样就可以ac 这个题了
吐槽一下 : 这个题没给m 的范围 emmm……..
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define ll long long
using namespace std;
const int INF = 1e9 + 7;
const int maxn = 1e6 + 10;
int n,m;
ll dp[1005][2] = {0};
ll a[maxn] = {0};
int main () {
while (scanf ("%d%d",&m,&n) != EOF) {
for (int i = 1;i <= n; ++ i) {
scanf ("%lld",&a[i]);
}
for (int i = 0;i <= m; ++ i) dp[i][0] = dp[i][1] = -INF;
dp[0][0] = 0;
for (int i = 1;i <= n; ++ i) {
int lim = min (i,m);
for (int j = 1;j <= lim; ++ j) {
dp[j][0] = max (dp[j][1],dp[j][0]);
dp[j][1] = max (dp[j][1],dp[j - 1][0]) + a[i];
}
}
printf ("%lld\n",max (dp[m][1],dp[m][0]));
}
return 0;
}