最大子段和或称为最大部分和(maximum subtotal)问题,以下简称MS。

  • MS:给定一类特定的数据类型的序列:[x1,x2,x3,x4,x5,x6],从该序列截取一段连续的子序列,如果这个子序列和满足整个序列的任意序列的最大值,我们称之为最大子段和。

     Sample:sequence:{6, -3, -4, 7, -1, 5, -3, -4, 8, -2};subSequence:6 -3、 -1 5 -3等;MS:7 -1 5 -3 -4 8
    

举例说明
例如:
则其最大字段和为:3+(−2)+5=6

暴力破解(Brute Force):
可以从串的任意位置开始在连续的任意位置结束,一层循环控制起始位置,一层循环控制结束位置。

复杂度:O(n^2)

//迭代
#include<iostream>
#include<algorithm>using namespace std;const int MaxNum = 100001;
const int MinINF = -1000003;
int numn;
int sequence[MaxNum];int main()
{while(cin>>numn){sequence[0] = MinINF;for(int i = 1; i <= numn; ++i){cin>>sequence[i];}for(int i = 1; i <= numn; ++i){int temporary = 0;for(int j = i; j <= numn; ++j){temporary += sequence[j];sequence[0] = max(sequence[0], temporary);}}cout<<sequence[0]<<endl;}return 0;
}

动态规划(Dynamic Programming):

  • 有暴力破解我们可以得到j这层循环本质是在求解当前位置开头的所有前缀最大和;
  • 子序列递增具备连续性质
  • 定义:dp[i]为能连续并到我当前位置的最大和:

令b[j]表示以位置 j 为终点的所有子区间中和最大的一个
子问题:如j为终点的最大子区间包含了位置j-1,则以j-1为终点的最大子区间必然包括在其中
如果dp[j-1] >0, 那么显然dp[j] = dp[j-1] + seq[j],用之前最大的一个加上a[j]即可,因为seq[j]必须包含
如果dp[j-1]<=0,那么dp[j] = seq[j] ,因为既然最大,前面的负数必然不能使你更大
对于这种子问题结构和最优化问题的证明,可以参考算法导论上的“剪切法”,即如果不包括子问题的最优解,把你假设的解粘帖上去,会得出子问题的最优化矛盾.证明如下:

令seq[x,y]表示seq[x]+…+seq[y] , y>=x
假设以j为终点的最大子区间 [s, j] 包含了j-1这个位置,以j-1为终点的最大子区间[ r, j-1]并不包含其中
即假设[r,j-1]不是[s,j]的子区间
存在s使得seq[s, j-1]+a[j]为以j为终点的最大子段和,这里的 r != s
由于[r, j -1]是最优解, 所以a[s,j-1]

得到状态转移方程:dp[i] = max(seq[i], dp[i-1]+seq[i]) | 1 <= j <= n && dp[i] >= 0;

seq[i] | dp[i] < 0;

例如,若a序列为(-2,11,-4,13,-5,-2),dp[0]=0,求其他元素如下:

(1)dp[1]=max{dp[0]+(-2),-2}=max{-2,-2}=-2

(2)dp[2]=max{dp[1]+11,11}=max{9,11}=11

(3)dp[3]=max{dp[2]+(-4),-4}=max{7,-4}=7

(4)dp[4]=max{dp[3]+13,13}=max{20,13}=20

(5)dp[5]=max{dp[4]+(-5),-5}=max{15,-5}=15

(6)dp[6]=max{dp[5]+(-2),-2}=max{13,-2}=13

其中,dp[4]=20为最大值,向前找到dp[1]小于等于0,所以由a2~a4的元素即(11,-4,13)构成最大子段和,其和为20

复杂度:O(n),由上式可以看出,如果dp[i]为负数,就没有在赋能的意义了,所以dp[i]数组可以不需要,空间复杂度:S(1)。

#include<iostream>
#include<algorithm>using namespace std;const int MinINF = -1000003;int numn;
int maxnum;int main()
{while(cin>>numn){maxnum = MinINF;int temporary;int tempsum = 0;for(int i = 1; i <= numn; ++i){cin>>temporary;if(tempsum >= 0){tempsum += temporary;}if(tempsum < 0){tempsum = temporary;}maxnum = max(maxnum, tempsum);}cout<<maxnum<<endl;}return 0;
}

分治(Divide and conquer):
产生最大子段和可以由三种情况得出:

  • 1)最大的子段和在序列的左边
  • 2)最大的子段和在序列的右边
  • 3)最大的子段和等于左边加右边

hint:合并的过程要是连续的

复杂度:T(n) = 2T(n/2) + O(n);即:O(nlgn)

#include<iostream>
#include<algorithm>using namespace std;const int MaxNum = 100001;
const int MinINF = -1000003;
int numn;
int sequence[MaxNum];int MergeMax(int x, int y, int z)
{x = x > y ? x : y;x = x > z ? x : z;return x;
}int MaxSum(int left, int right)
{int sum = 0;if(left == right){return sequence[left] >= 0 ? sequence[left] : 0;}else{int mid = (right+left)/2;int leftsum = MaxSum(left, mid);int rightsum = MaxSum(mid+1, right);int maxnum1 = MinINF;int tempsum1 = 0;for(int i = mid; i >= left; --i){tempsum1 += sequence[i];if(tempsum1 > maxnum1)maxnum1 = tempsum1;}int maxnum2 = MinINF;int tempsum2 = 0;    for(int i = mid+1; i <= right; ++i){tempsum2 += sequence[i];if( tempsum2> tempsum2)maxnum2 = tempsum2;}sum = maxnum1+maxnum2;sum = MergeMax(sum, leftsum, rightsum);}  return sum;
}int main()
{while(cin>>numn){for(int i = 0; i < numn; ++i){cin>>sequence[i];}cout<<MaxSum(0, numn)<<endl;}return 0;
}

最大子矩阵和(Maximum subMatrix)问题:对最大子段和的升维

问题大意:给定一个矩阵,求最大值子矩阵。

我们可以对矩阵向下叠加转化为最子段和问题,即当前点为末位边角元素所有矩阵的最大和:这样就可以对行不断向下叠加操作行次求解子段最大和便得到结果。

//poj1050为例
#include<iostream>
#include<algorithm>
#include<string.h>const int MaxNum = 101;
const int MinINF = -100003;int dp[MaxNum];
int matrix[MaxNum][MaxNum];
int numn;
int maxnum;using namespace std;int main()
{while(cin>>numn){for(int i = 0; i < numn; ++i)for(int j = 0; j < numn; ++j)cin>>matrix[i][j];maxnum = MinINF;for(int i = 0; i < numn; ++i){memset(dp, 0, sizeof(dp));for(int j = i; j < numn; ++j){int tempsum = 0;for(int k = 0; k < numn; ++k){dp[k] += matrix[j][k];if(tempsum >= 0){tempsum += dp[k];}if(tempsum < 0){tempsum = dp[k];}maxnum = max(maxnum, tempsum);}}}cout<<maxnum<<endl;}return 0;
}

最大子段和问题——详解(C++)相关推荐

  1. leetcode53. 最大子序和详解——pygo

    题目连接: 53. 最大子序和https://leetcode-cn.com/problems/maximum-subarray/ 之前有总结过C++实现: 最大子段和问题--详解(C++):http ...

  2. Transformer结构详解(有图,有细节)

    文章目录 1. transformer的基本结构 2. 模块详解 2.1 模块1:Positional Embedding 2.2 模块2:Multi-Head Attention 2.2.1 Sca ...

  3. 一文详解 MySQL 高可用之 DRBD | 原力计划

    作者 | wzy0623 责编 | 屠敏 出品 | CSDN 博客 大多数MySQL高可用解决方案都是基于MySQL自带的各种复制技术.本质上是将一个实例上的数据更新或事务,在其它实例上进行重放,从而 ...

  4. 路由器访问控制列表详解

    路由器访问控制列表详解 路由器访问控制列表详解 网络安全保障的第一道关卡 对于许多网管员来说,配置路由器的访问控制列表是一件经常性的工作,可以说,路由器的访问控制列表是网络安全保障的第一道关卡.访问列 ...

  5. 没有执行此操作所需的足够可用空间。_一文详解 MySQL 高可用之 DRBD | 原力计划...

    作者 | wzy0623责编 | 屠敏出品 | CSDN 博客大多数MySQL高可用解决方案都是基于MySQL自带的各种复制技术.本质上是将一个实例上的数据更新或事务,在其它实例上进行重放,从而完成数 ...

  6. RedisBloom 插件布隆过滤器,布谷鸟过滤器,Count-Min Sketch,TOPK使用详解

    文章目录 前言 一.如何安装 二.布隆过滤器 1. 使用介绍 2. 命令详解 三.布谷鸟过滤器 1. 使用介绍 2. 命令详解 三.Count-Min Sketch 1. 使用介绍 2. 命令详解 四 ...

  7. JavaMail详解

    引用自http://blog.sina.com.cn/s/articlelist_1832656582_7_1.html [JavaMail]1 基础 A.简介 JavaMail,顾名思义,提供给开发 ...

  8. Transformer(二)--论文理解:transformer 结构详解

    转载请注明出处:https://blog.csdn.net/nocml/article/details/110920221 本系列传送门: Transformer(一)–论文翻译:Attention ...

  9. 传输协议之ICMP详解

    文章目录 TCP和UDP ICMP 简介 ICMP出现的原因 ICMP的用途 ICMP作为IP的上层协议在工作(报文) ICMP实现之MTU探索 ICMP实现之改变路由 ICMP实现之源点抑制 ICM ...

最新文章

  1. 【有奖征文】如何提高IDC机房服务器的安全性
  2. 【零散积累】 vim常用操作
  3. Android - 布局详解之LinearLayout与RelativeLayout
  4. Leetcode--319. 灯泡开关
  5. 转:VMware、微软等四种主要的网络IO虚拟化模型
  6. SqlServer判断数据库、表、字段、存储过程、函数是否存在
  7. cheatsheet 常用图标大全
  8. CLR via C# 3rd - 07 - Constants and Fields
  9. 钝化 会钝化 订单审批流程 码一会er
  10. web项目移动端在线预览(excel在线预览)
  11. 谷歌浏览器下载更新(附带谷歌安装包百度云)
  12. 三点确定圆的半径_51CAE_新浪博客
  13. Android控件详解之网格控件
  14. 地对地导弹地对地导弹
  15. undefined reference to `__stack_chk_guard‘ .. undefined reference to `__stack_chk_fail‘
  16. SSH——Hibernate初学者之旅(五)
  17. 巴比特MatPool运营NEO节点,2019年必定是 Staking 经济元年
  18. 计算机学 英文,计算机英语学习
  19. python生成exe启动很慢_python生成exe启动很慢|Win7电脑启动慢如何解决?Win7使用Msconfig.exe解决电脑启动慢的方法...
  20. pytorch distiller filter channel剪枝

热门文章

  1. OpenJDK-11的新特征
  2. Docker快速安装Sybase数据库DBeaver数据库图形化管理开发工具
  3. spring cloud之Feign的使用
  4. C 语言实例 - 斐波那契数列
  5. mitmproxy可谓神器乎?
  6. 仅30分钟,在同一台设备安装discourse和wordpress
  7. error while loading shared libraries: libiconv.so.2: cannot open shared object file
  8. PyTorch入门-简单图片分类
  9. 用Python手写五大经典排序算法,看完这篇终于懂了!
  10. Python 爬虫是什么