就是按着DP的思路来做的,结果还是想不到。T_T,行了,别玻璃心了,继续。
这道题目是求在一列数里,由两部分子段和组成的最大和。即对于连续整数组成的串 S1、S2,使 S1 + S2 的和最大。
题目与求最大子段和有相似之处,可以说是最大子段和的变形。
最大子段和:
在一列数里,对于连续整数组成的串S,使 S 的值最大。
最大子段和的动态规划方程, dp[i] = max(dp[i-1] + arr[i], arr[i]); 意义:当遍历到当前第 i 个数时,比较 {前一状态dp[i-1] 加上当前数 arr[i]} 与 {arr[i]的大小},选取大的为当前状态。 其实 也就是看 dp[i-1] 是否大于0。
回到这个题目,我们进行的操作是,先从 0 -> n-1 算一次最大子段和,记录在 lft[] 中; 然后再从 n-1 -> 0 倒着算一次最大子段和,记录在rht[]中。
我们要再从 0 -> n-1 遍历一遍看,在当前状态 i 为基准的情况,将它的前半段 和 后半段的值加起来,然后在这里边找最大。
因为在求最大 Max 时, 前半段一定,可以直接用lft[],而后半段是到当前后半段里的最大值,所以还要进行一次操作找出每个位置之后最大值。
动态规划路还很长啊!
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 const int MAXN = 500100; 6 int lft[MAXN]; 7 int rht[MAXN]; 8 int arr[MAXN]; 9 10 int main() { 11 int T; 12 scanf("%d", &T); 13 while(T--) { 14 int n; 15 scanf("%d", &n); 16 for(int i = 0; i < n; ++i) 17 scanf("%d", arr+i); 18 lft[0] = arr[0], rht[n-1] = arr[n-1]; 19 for(int i = 1; i < n; ++i) //求到 i 的位置时, 最大子段和 20 lft[i] = max(arr[i], lft[i-1] + arr[i]); 21 for(int i = n-2; i >= 0; --i) // 反过来求到 i 的位置时,最大子段和 22 rht[i] = max(arr[i], rht[i+1] + arr[i]); 23 for(int i = n-2; i >= 0; --i) // 在计算两部分相加的时候,后边是从当前到最后所有最短和最大的 24 rht[i] = max(rht[i+1], rht[i]); 25 int Max = -1000000; 26 for(int i = 0; i < n-1; ++i) //计算由两部分组成的子段和里的最大值 27 Max = max(Max, lft[i] + rht[i+1]); 28 printf("%d ", Max); 29 } 30 return 0; 31 }
2593与2479一模一样