2018-01-14 21:14:58

一、最大子段和问题

问题描述:给定n个整数(可能有负数)组成的序列a1,a2,...,an,求该序列的最大子段和。如果所有整数都是负数,那么定义其最大子段和为0。

方法一、最大子段和的简单算法

显然可以在O(n^2)的时间复杂度上完成这个问题。但是是否可以对算法进行优化呢?答案是肯定的。

方法二、分治算法

朴素的分法是二分,问题就是如何merge,在merge的时候,因为已经确定了会包含边界点,所以可以在O(n)的时间复杂度上完成merge时的最大子段和。

因此分治公式是:T(n) = 2T(n/2)+O(n)

根据主定理可以算得,分治算法的时间复杂度为O(nlgn)。

int maxSubSum(int[] a,int L,int R){

if(L == R) return a[L] > 0 ? a[L] : 0;

else {

int mid = L + (R - L) / 2;

int sumL = maxSubSum(a, L, mid);

int sumR = maxSubSum(a, mid + 1, R);

int tmpL = 0;

int tmpR = 0;

int sum = 0;

for (int i = mid; i >=0 ; i--) {

sum += a[i];

if(sum>tmpL) tmpL = sum;

}

sum = 0;

for (int i = mid+1; i <=R ; i++) {

sum += a[i];

if(sum>tmpR) tmpR = sum;

}

return Math.max(sumL,Math.max(sumR,tmpL+tmpR));

}

}

方法三、动态规划

这种两端都是变化的问题是很难优化的,最好可以让一端固定,这样就会大大简化分析难度。于是将j暂时从原式子中提取出来,将剩下的命名为b[j]。

所以原问题就变成了这样。

根据b[j]的定义,b[j]是指以a[j]结尾的最大子段和。因此有如下公式:

b[j] = max{b[j - 1] + a[j] , a[j]}      1=

有了b[j],再对他取个极值,就可以得到原问题的解。

时间复杂度为O(n)

int maxSum(int[] a) {

int res = 0;

int b = 0;

for (int i = 0; i < a.length; i++) {

b = Math.max(b + a[i], a[i]);

if (b > res) res = b;

}

return res;

}

二、推广问题

最大子矩阵和问题

问题描述:给定一个m*n的整数矩阵A,试求矩阵A的一个子矩阵,使其各个元素之和最大。

问题分析:事实上,只需要将矩阵“压扁”就可以规约到最大子段和问题,具体来说就是将多行进行求和变为一行,这样就可以直接使用上述问题的解法。将多行“压缩”成一行有多种可行方案,需要遍历一下,花费O(m^2),最大子段和动态规划算法花费O(n),所以总的时间消耗是O(m^2*n)。

最大m子段和问题

问题描述:给定n个整数(可能有负数)组成的序列a1,a2,...,an,以及一个正整数m,要求确定该序列的m个不相交子段,使这m个子段的总和最大。

问题分析:设b(i, j)表示数组a的前j项中i个子段和的最大值,且第i个子段含a[j](1<=i<=m,i<=j<=n),则所求的最优值显然为max b(m, j),其中 m <= j <= n。

与最大子段和类似。计算b(i,j)的递归式子为:

b(i, j) = max{ b(i, j-1) + a[j] , max{ b(i - 1, t) + a[j] 其中t = i - 1 ~ j - 1} }

初始时,b(0, j) = 0; b(i, 0) = 0。

#include "stdafx.h"

#include

using namespace std;

int MaxSum(int m,int n,int *a);

int main() {

int a[] = {0,2,3,-7,6,4,-5};//数组脚标从1开始

for(int i=1; i<=6; i++) {

cout<

}

cout<

cout<

}

int MaxSum(int m,int n,int *a) {

if(n

return 0;

int **b = new int *[m+1];

for(int i=0; i<=m; i++) {

b[i] = new int[n+1];

}

for(int i=0; i<=m; i++) {

b[i][0] = 0;

}

for(int j=1;j<=n; j++) {

b[0][j] = 0;

}

//枚举子段数目,从1开始,迭代到m,递推出b[i][j]的值

for(int i=1; i<=m; i++) {

//n-m+i限制避免多余运算,当i=m时,j最大为n,可据此递推所有情形

for(int j=i; j<=n-m+i; j++) {

if(j>i) {

b[i][j] = b[i][j-1] + a[j];//代表a[j]同a[j-1]一起,都在最后一子段中

for(int k=i-1; k

if(b[i][j]

b[i][j] = b[i-1][k]+a[j];//代表最后一子段仅包含a[j]

}

}

else {

b[i][j] = b[i-1][j-1]+a[j];//当i=j时,每一项为一子段

}

}

}

int sum = 0;

for(int j=m; j<=n; j++) {

if(sum

sum = b[m][j];

}

}

return sum;

}

上述算法显然需要O(m*n^2)计算时间和O(m*n)。可以看一下具体矩阵是怎么填写的。

注意到上述算法中,计算b[i][j]时只用到了b的当前行的前一个数以及上一行的一个极值。因此我们可以定义两个数组,一个数组来保存当前行,一个数组来保存上一行的极值。并且使用数组来保存极值可以边生成当前行的数值边进行极值的判断并进行填充。

#include "stdafx.h"

#include

using namespace std;

int MaxSum(int m,int n,int *a);

int main() {

int a[] = {0,2,3,-7,6,4,-5};//数组脚标从1开始

for(int i=1; i<=6; i++) {

cout<

java动态规划求最大子段和_动态规划-最大子段和相关推荐

  1. java 最少货币单元组合换钱_动态规划. 换钱的最少货币数和最多方法数

    通过对换钱类题目的学习,我们将了解到 暴力递归及优化方法 记忆搜索(优化一) 动态规划的基本实现方法(优化二) 动态规划的空间优化(优化三) 1. 换钱的最少货币数,货币可重复使用 给定数组arr,a ...

  2. java动态规划求最大子段和_动态规划:求最大子段和

    动态规划:求最大子段和 1.题目 2.方法 3.实现代码 //动态规划法求最大子段和 // by 孙琨SealSun at UCAS // 2015.11.20 #include using name ...

  3. java迭代法求圆周率用梯形_常用的圆周率计算公式

    (I)设备筒体.管道表面积计算公式为: S=πDL (1-2) 式中 π--圆周率,取 3.14; D--设备简体.管道直径(m); L--设备筒体.管道高或延长米(m)...... (二)椭圆面积计 ...

  4. java迭代法求圆周率用梯形_感悟数学“近似计算”之美——“望星楼”里的圆周率...

    人类求解圆周率的历史非常悠久.在数学史上,圆周率的计算方法大体上可以分为两类:早期大多使用的是几何算术方法,即利用多边形逼近单位圆来近似求解:第二类是近现代数学中的解析方法.本文主要讲前者,读者们一般 ...

  5. JAVA编程求单源最短路径_【算法】单源最短路径——dijkstra算法

    一,概念 单源最短路径 给定一个带权有向图G=(V,E),其中每条边的权是一个实数.另外,还给定V中的一个顶点,称为源.要计算从源到其他所有各顶点的最短路径长度.这里的长度就是指路上各边权之和.这个问 ...

  6. java如何求矩阵的置换_矩阵乘法(五):置换

    矩阵乘法在一些置换问题上有着很好的应用,特别置换次数较多时,采用矩阵快速幂运算可以加快运算过程. 任意一个置换都能够表示成矩阵的形式.比如,将序列1  2  3  4 置换为 3  1  2  4,相 ...

  7. java链表求平均值和方差_用c语言链表求n个数的均值和标准差

    匿名用户 1级 2015-06-15 回答 //解决问题的思路 //1. 建立数学模型 //    均值avg = (a1+a2+...an)/n //    标准差sd^2 = [(a1-avg)^ ...

  8. 旅游路线最短matlab,动态规划求最短旅行路线.doc

    动态规划求最短旅行路线.doc 动态规划求最短旅行路线摘要在我们日常生活和旅行中经常遇到求最短路径的问题,将动态规划思想运用到求解旅行问题最短路径中,将过程划分为几个阶段,在每阶段中选取最优策略,最后 ...

  9. 最大子段和动态规划_动态规划解最大子段和问题

    1 动态规划 1.1 基本思想 动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题. 与分治法的区别在于,适用于动态规划算法求解的问题,经分解得到的子问题往往不是互相独立的:若用分 ...

  10. java 爬楼梯算法_动态规划-爬楼梯问题java实现

    最近开始看算法导论,研究了一下动态规划,下面就开始直入主题开始记录近期看的第一个知识点动态规划.提起动态规划就不得不提几个动态规划的金典问题爬楼梯.国王金矿.背包问题.今天就仔细分析一下爬楼梯问题. ...

最新文章

  1. java实现时间的比较
  2. RDKit | 比较分子之间的相似性
  3. 在Linux的Eclipse下搭建Android环境
  4. raspberry pi_如何在Raspberry Pi上使用LÖVE游戏引擎对游戏进行编程
  5. [USACO17FEB] Why Did the Cow Cross the Road I P (树状数组求逆序对 易错题)
  6. Java学习作业(14.4.21)
  7. 读《操作系统之哲学原理》的一点感想
  8. [转]C#:手把手教你用C#打包应用程序(安装程序卸载程序)
  9. 批处理添加允许弹出临时窗口站点
  10. discuz升级php版本版本502,dz2.5版本升级Discuz! X3.0详细教程
  11. 分析setting源代码获取sd卡大小
  12. 流媒体技术笔记(DarwinStreamingServer相关)
  13. mysql数据库学习——2,数据库的选定,创建,删除和变更
  14. bp神经网络的训练方法,一文搞定bp神经网络
  15. 3t studio 导出数据_Studio 3T下操作MongoDB的基本命令(转载)
  16. 单交换机的VLAN的配置
  17. 大学三年软件工程专业学习感受
  18. 用自己的APP打开微信和支付宝付款码和扫一扫界面
  19. Machine Learning Practical 爱宝week2
  20. [PHP问题]Cannot redeclare xxxxxx() (previously declared in C:\WWW\xxx.xxx:xxx)

热门文章

  1. 我的世界php motd,我的世界motd标语编辑器
  2. 小宝机器人怎么开机_小宝机器人用户手册.PDF
  3. 140个电脑小知识、小技巧(2)
  4. plt图像保存到pdf文件
  5. Halcon教程八:简单的语法介绍
  6. windows11,安装maven。
  7. 大专大一计算机应用基础期末考试题,计算机基础大一考试题及答案
  8. Unity 3D 2022.1 AND UnityHub 3.2 Patch
  9. matlab中fft与fftshift,在matlab中使用fft,ifft和fftshift
  10. 网站ping端口的操作方法和命令介绍