题目大意

给定一列数,从中选择两个不相交的连续子段,求这两个连续子段和的最大值。

题目分析

典型的M子段和的问题,使用动态规划的方法来解决。

f[i][j] 表示将A[1...i] 划分为j个不相交连续子串,且A[j]属于第i个子串,所能达到的最大子串和 
g[i][j] 表示将A[1...j]划分为i个不相交连续子串,且A[j]不一定属于第i个子串,所能达到的最大子串和 
f[i][j] = max{f[i-1][j] + A[i], g[i-1][j-1] + A[i]} 
g[i][j] = max{g[i-1][j], f[i][j]}; 
进行空间优化之后: 
f[j] = max{f[j], g[j-1]} + A[i] 
g[j - 1] = max(g[j - 1], f[j - 1]); 
注意f和g的循环层次不同.这是因为:在外部进行到第i层循环的时候,f[i][j] = max{f[i-1][j] + A[i], g[i-1][j-1] + A[i]} 中max{}中的 f[j]和g[j-1]用的是第i-1层循环的时候的 f[j]和 g[j-1]; 若写成f[j] = max(f[j] + A[i], g[j - 1] + A[i]);g[j] = max(g[j], f[j]); 
则本次的g[j]变成了第i次循环的g[j],而下次循环的 f[j] = max{} 中g[j-1]变成了第i次循环的g[j],而不是第i-1次循环的g[j]因此,写成 g[j-1] = max(g[j-1], f[j-1]); 使得 每次执行 
for (j = 1; j <= m; j++){ 
f[j] = max(f[j] + A[i], g[j-1] + A[i]); 
g[j-1] = max(g[j-1], f[j-1]); 

的时候, f[j]都使用第i-1层的f[j]和g[j-1],而g[j-1]使用的是第i-1层的g[j-1]和第i层的f[j]

实现(c++)

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<stdio.h>
  3. #include<string.h>
  4. #define MAX_LEN 50005
  5. #define INFINITE 1 << 30
  6. #define max(a, b) a > b? a:b
  7. long long int f[MAX_LEN];
  8. long long int g[MAX_LEN];
  9. int A[MAX_LEN];
  10. /*f[i][j] 表示将A[1...i] 划分为j个不相交连续子串,且A[j]属于第i个子串,所能达到的最大子串和
  11. g[i][j] 表示将A[1...j] 划分为i个不相交连续子串,且A[j]不一定属于第i个子串,所能达到的最大子串和
  12. f[i][j] = max{f[i-1][j] + A[i], g[i-1][j-1] + A[i]}
  13. g[i][j] = max{g[i-1][j], f[i][j]};
  14. 进行空间优化之后:
  15. f[j] = max{f[j], g[j-1]} + A[i]
  16. g[j - 1] = max(g[j - 1], f[j - 1]);
  17. 注意f和g的循环层次不同
  18. 这是因为:在外部进行到第i层循环的时候,f[i][j] = max{f[i-1][j] + A[i], g[i-1][j-1] + A[i]} 中max{}中的 f[j]和g[j-1]用的是
  19. 第i-1层循环的时候的 f[j]和 g[j-1];
  20. 若写成
  21. f[j] = max(f[j] + A[i], g[j - 1] + A[i]);
  22. g[j] = max(g[j], f[j]);
  23. 则本次的g[j]变成了第i次循环的g[j],而下次循环的 f[j] = max{} 中 g[j-1]变成了第i次循环的g[j],而不是第i-1次循环的g[j]
  24. 因此,写成 g[j-1] = max(g[j-1], f[j-1]); 使得 每次执行
  25. for (j = 1; j <= m; j++){
  26. f[j] = max(f[j] + A[i], g[j-1] + A[i]);
  27. g[j-1] = max(g[j-1], f[j-1]);
  28. }
  29. 的时候, f[j]都使用第i-1层的f[j]和g[j-1],而g[j-1]使用的是第i-1层的g[j-1]和第i层的f[j]
  30. */
  31. long long int MaxSum(int m, int n){
  32. int i, j;
  33. for (i = 1; i <= n; i++){
  34. for (j = 1; j <= m; j++){
  35. f[j] = max(f[j] + A[i], g[j-1] + A[i]);
  36. g[j-1] = max(g[j-1], f[j-1]);
  37. }
  38. g[j - 1] = max(g[j - 1], f[j - 1]);
  39. }
  40. return g[m];
  41. }
  42.  
  43. int main(){
  44. int cas;
  45. scanf("%d", &cas);
  46. while (cas--){
  47. int n;
  48. scanf("%d", &n);
  49.  
  50. f[0] = g[0] = 0;
  51. for (int i = 1; i <= n; i++){
  52. f[i] = g[i] = -INFINITE;
  53. scanf("%d", A + i);
  54. }
  55. long long int max_sum = MaxSum(2, n);
  56. printf("%lld\n", max_sum);
  57. }
  58. return 0;
  59. }

poj_2479 动态规划的更多相关文章

  1. 增强学习(三)----- MDP的动态规划解法

    上一篇我们已经说到了,增强学习的目的就是求解马尔可夫决策过程(MDP)的最优策略,使其在任意初始状态下,都能获得最大的Vπ值.(本文不考虑非马尔可夫环境和不完全可观测马尔可夫决策过程(POMDP)中的 ...

  2. 简单动态规划-LeetCode198

    题目:House Robber You are a professional robber planning to rob houses along a street. Each house has ...

  3. 动态规划 Dynamic Programming

    March 26, 2013 作者:Hawstein 出处:http://hawstein.com/posts/dp-novice-to-advanced.html 声明:本文采用以下协议进行授权: ...

  4. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

  5. C#动态规划查找两个字符串最大子串

     //动态规划查找两个字符串最大子串         public static string lcs(string word1, string word2)         {            ...

  6. C#递归、动态规划计算斐波那契数列

    //递归         public static long recurFib(int num)         {             if (num < 2)              ...

  7. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  8. 【BZOJ1700】[Usaco2007 Jan]Problem Solving 解题 动态规划

    [BZOJ1700][Usaco2007 Jan]Problem Solving 解题 Description 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地 ...

  9. POJ 1163 The Triangle(简单动态规划)

    http://poj.org/problem?id=1163 The Triangle Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

随机推荐

  1. python --循环对象

    转自:http://www.cnblogs.com/vamei/archive/2012/07/09/2582499.html 这一讲的主要目的是为了大家在读Python程序的时候对循环对象有一个基本 ...

  2. [Jobdu] 题目1139:最大子矩阵

    题目描述: 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵.比如,如下4 * 4的矩阵 0 -2 -7 09 2 -6 2-4 1 -4 ...

  3. 安卓开发学习2-官方例子Accelerometer

    1.使用WakeLock防止屏幕被锁住,如果用户自己锁住屏幕,下次再开的时候还会重置一下,防止被锁. 2.SimulationView接收传感器事件,并且绘制.它实现SensorEventListen ...

  4. atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结

    atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结 1.   应用场景:::DSL 大大提升开发效率 1 2. 2. 流程如下::: 词法分析(生成toke ...

  5. [vt]xenserver磁盘扩容扩不大问题解决

    xenserver将磁盘扩大后,fdisk可以看到容量大了,但是df -h看到磁盘并没有大,解决. 参考 说明:XenServer里面安装的虚拟机,分区的时候采用的是LVM磁盘分区 需求:现在需要扩容 ...

  6. CXCommon.h工具类

    #ifndef __XCOMMON_H__ #define __XCOMMON_H__ /******************************************************* ...

  7. HDU 3336 Count the string 查找匹配字符串

    Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. ng-class中的if else判断

    ng-class中的if else判断 来自于stackoverflow的一个问题,自己刚好用到,搬过来做个标记.原问题链接 在使用ng-class时,有些时候会碰到根据是否满足条件来设置元素的样式, ...

  9. Hive入门笔记---1.Hive简单介绍

    1. Hive是什么 Hive是基于Hadoop的数据仓库解决方案.由于Hadoop本身在数据存储和计算方面有很好的可扩展性和高容错性,因此使用Hive构建的数据仓库也秉承了这些特性.这是来自官方的解 ...

  10. sparksql 操作hive

    写在前面:hive的版本是1.2.1spark的版本是1.6.x http://spark.apache.org/docs/1.6.1/sql-programming-guide.html#hive- ...