51nod-1052 最大M子段和

来源:互联网 发布:mac 安装lamp 编辑:程序博客网 时间:2024/06/01 07:50

原题链接

1052 最大M子段和
基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
 收藏
 关注
N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。
例如:-2 11 -4 13 -5 -2,分为2段,11 -4 13一段,6一段,和为26。
Input
第1行:2个数N和M,中间用空格分隔。N为整数的个数,M为划分为多少段。(2 <= N , M <= 5000)第2 - N+1行:N个整数 (-10^9 <= a[i] <= 10^9)
Output
输出这个最大和
Input示例
7 2-211-413-56-2
Output示例
26

用dp[i][j]表示以i结尾的数组被分为j段的最大和(第j个数字一定要用) dp[i][j] = max(dp[i-1][j], d) + num[j], 其中d = max(dp[h][j-1]) h < i

因为空间限制,要用滚动数组

#include <bits/stdc++.h>#define MOD 1000000007#define maxn 5005#define INF 1e18using namespace std;typedef long long ll;int num[maxn];ll dp[maxn][2];int main(){//freopen("in.txt", "r", stdin);ll p = 0;int n, m, k = 0;scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++){scanf("%d", num+i);if(num[i] > 0){k++;p += num[i];}}if(m >= k){printf("%I64d\n", p);return 0;}int e = 1;for(int i = 1; i <= m; i++){ ll d = dp[0][e^1]; for(int j = 1; j <= n; j++){ dp[j][e] = max(dp[j-1][e], d) + num[j]; d = max(d, dp[j][e^1]); } for(int j = 0; j < i; j++)  dp[j][e] = -INF; e ^= 1;    }ll maxs = 0;for(int i = 0; i <= n; i++){ maxs = max(maxs, dp[i][e^1]);   }cout << maxs << endl;return 0; }



0 0