本题就是求m段子段,而且要求这些子段加起来和最大,最大子段和的Plus版本。
不过题意真的不好理解,x,y什么的都没有说清楚。
知道题意就开始解题了,这肯定是动态规划法了。
动态规划法的程序不难写,关键是抽象思维。
这里的最小情况是只分成一段的时候,就退化为最大子段和问题了,这个是段数的最小情况了; 如果只有0个数的时候,结果肯定为零了,或者如果只有一个数的时候就是这个数了,那么数列只有0个或者1个的时候就是数组的最小情况了。
然后记录使用一个数组记录dp[MAX_N],其中dp[i]的含义就是在一定选择i这个数的时候得到的最大和值。
这样如果分成i段,有j个数的时候dp[j] = max(dp[j-1]+arr[j], MAX[j-1]+arr[j]),其实如果使用二维数组,那么MAX[j-1] == dp[[i-1][j-1]这个状态格的数值,表示分成i-1段的时候,有j-1个数的值。取max就是表示arr[j]是直接和dp[j-1]即接在后面第i段,还是独立成为一段的值比较大,选择最优方案,取最大值。这里的记录数据方案就是所谓的滚动数组了。不过我分开两个数组罢了。
抽象思维,比较难理解的,代码还是很好写的。
#include <stdio.h> #include <vector> #include <string.h> #include <algorithm> #include <iostream> #include <string> #include <limits.h> #include <stack> #include <queue> #include <set> #include <map> using namespace std; const int MAX_N = 1000001; int dp[MAX_N], MAX[MAX_N], arr[MAX_N]; int main() { int n, m, maxSum; while (~scanf("%d %d", &m, &n)) { memset(MAX, 0, sizeof(int) * (n+1)); memset(dp, 0, sizeof(int) * (n+1)); for (int i = 1; i <= n; i++) { scanf("%d", arr+i); } for (int i = 1; i <= m; i++) { maxSum = INT_MIN; for (int j = i; j <= n; j++) { dp[j] = max(dp[j-1]+arr[j], MAX[j-1]+arr[j]); MAX[j-1] = maxSum; //not overflow here maxSum = max(maxSum, dp[j]); } } printf("%d\n", maxSum); } return 0; }
HDU 1024 Max Sum Plus Plus Dp题解,布布扣,bubuko.com
HDU 1024 Max Sum Plus Plus Dp题解
原文:http://blog.csdn.net/kenden23/article/details/38583111