动态规划(Dynamic Programming):与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适用于动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。

  使用动态规划法求解的问题需要符合一些条件:

(1):所求解问题必须要符合最优子结构;(最优子结构即:原问题的最优解中包含了子问题的最优解)

(2):原问题分解出来的子问题相互之间存在联系,即递归时会重复解决之前已解决过的子问题。

  先说明一些前提:

(1):矩阵相乘的条件是:前一个矩阵的行数=后一个矩阵的列数;

(2):可以用数组p[0:n]来存放n个连乘矩阵的行数和列数(p[i-1]表示Ai的行数,p[i]表示Ai的列数);

(3):用A[i:j]表示Ai连乘到Aj,假设最优的加括号方式(最外层)是:(Ai*……*Ak)(Ak+1*……*Aj) 。

下面我们先从动态规划解决矩阵连乘问题的最初始的方法入手,代码如下:

 private static int recurMatrixChain(int i,int j,int[] p)   //最初始的矩阵连乘问题算法
{
if(i == j) return 0; //i == j,即只有一个矩阵,计算次数当然为零
int min = recurMatrixChain(i,i,p) + recurMatrixChain(i+1,j,p) + p[i-1] * p[i] * p[j];
for(int k = i + 1; k < j; k++){
int t = recurMatrixChain(i,k,p) + recurMatrixChain(k+1,j,p) + p[i-1] * p[k] * p[j];
if(t < min) min = t; //从k处断开,如果t比min更小,则说明存在更优的解决方法,把t赋值给min
}
return min;
}

  递归掌握得好的话,结合注释,理解起来并不会觉得困难。但这个方法存在一个严重的弊端,虽然能计算出最优解,但是在计算过程中,其实调用了指数级别次的方法,而这么多次调用其实都在解决重复子问题而已。

  下面介绍一种能解决上边提到的问题,动态规划解决矩阵连乘问题的第二种方法——备忘录方法,代码如下:

 private static int lookupChain(int i,int j,int[][] m,int[] p)
{
if(m[i][j] > 0) return m[i][j]; //如果m[i][j]非零,则说明该子问题被计算过,只需取出这个数,无需进行计算
if(i == j) return 0;
int min = lookupChain(i,i,m,p) + lookupChain(i+1,j,m,p) + p[i-1] * p[i] * p[j];
for(int k = i + 1; k < j; k++){
int t = lookupChain(i,k,m,p) + lookupChain(k+1,j,m,p) + p[i-1] * p[k] * p[j];
if(t < min) min = t;
}
m[i][j] = min; //对于未记录的子问题,通过计算把该子问题的最优解求出后,存放在数组中
return min;
} private static int memoizedMatrixChain(int n,int[][] m,int[] p) //这个就是解决矩阵连乘问题的备忘录方法
{
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
m[i][j] = 0; //对数组进行初始化
return lookupChain(1,n,m,p);
}

  我们可以看出,lookupChain方法跟recurMatrixChain方法其实差不多,只是加插了两行代码而已,而这就是两种算法之间的不同之处,就是最重要的地方。第一次调用时跟第一种方法一样,同时记录了子问题的最优解,当第二次调用时,便可以直接从备忘录中提取子问题的最优解,大大地减少了方法的调用次数。

  下面介绍另一种动态规划方法——填表法,我的老师将其称为真·动态规划,代码如下:

 private static void matrixChain(int n,int[][] m,int[] p){    //填表法,我的老师也叫这方法为真·动态规划方法
for(int i = n-1; i >= 1; i--)
for(int j = i+1; j <= n; j++){
int min = m[i][j] + m[i+1][j] + p[i-1] * p[i] * p[j];
for(int k = i+1; k < j; k++){
int t = m[i][k] + m[k+1][j] + p[i-1] * p[k] * p[j];
if(t < min) min = t;
}
m[i][j] = min;
}
}

  我们会发现,该算法其实跟第一种方法几乎相同,但是这个算法是直接用数组来存放子问题的最优解,跟备忘录方法稍有不同,而且这个算法并没有使用递归。而且这个填表法其实需要个人有比较强的能力,我们可以先举个简单点的例子,然后自己画一个二维数组,分析第一个数是填入到哪里,第二个数是填入到哪里,如此重复,找出规律后就可以开始编写自己的填表法了,在这里的是自下而上的填表法。

  到这里结束了,如果有不对的地方或者对这个算法有更好的建议,欢迎指出!

(基于Java)算法之动态规划——矩阵连乘问题的更多相关文章

  1. Java算法——动态规划

    基本思想: 动态规划算法通常用于求解具有某种最优性质的问题(作用就是求最优解).在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解.动态规划算法与分治法类似,其基本思 ...

  2. 排序算法总结(基于Java实现)

    前言 下面会讲到一些简单的排序算法(均基于java实现),并给出实现和效率分析. 使用的基类如下: 注意:抽象函数应为public的,我就不改代码了 public abstract class Sor ...

  3. 一个基于RSA算法的Java数字签名例子

    原文地址:一个基于RSA算法的Java数字签名例子 一.前言: 网络数据安全包括数据的本身的安全性.数据的完整性(防止篡改).数据来源的不可否认性等要素.对数据采用加密算法加密可以保证数据本身的安全性 ...

  4. 基于Java实现的冒泡排序算法

    冒泡排序是一种简单基础的排序算法,相信在大学课堂里老师已经讲过了,现在我基于Java来实现一遍. 简述 冒泡排序正如其关键词一样,杂乱的气泡经过浮动,最后大的气泡飘到了上面而小的气泡在下面,无序的元素 ...

  5. 算法(Java实现)—— 动态规划算法

    动态规划算法 应用场景-0-1背包问题 背包问题:有一个背包,容量为4磅,现有物品如下 物品 重量 价格 吉他(G) 1 1500 音响(S) 4 3000 电脑(L) 3 2000 要求: 达到目标 ...

  6. 基于java平台的常用资源整理

    这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...

  7. 这里整理了基于java平台的常用资源

    这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...

  8. 基于java的设计模式入门(1)——为什么要学习设计模式

    大年初一,楼主在这里给大家拜年,祝大家码上升职加薪,码上有对象结婚,码上有车有房,幸福安康. 过完年,回学校注册报道之后,大概就要回深圳到公司开始实习了.提高自己,无非就有两种方式,一是看书学习,二是 ...

  9. 动态规划&矩阵连乘

    动态规划&矩阵连乘 动态规划的概念 •     与分治方法类似       分-治-合 • 与分治方法不同       子问题之间并非相互独立 •     基本思想        用一个表记录 ...

随机推荐

  1. Documentation/filesystems/sysfs.txt 文档翻译--sysfs

    sysfs - 用于导出内核对象的文件系统. 1.sysfs是一个基于ram的文件系统,最初基于ramfs. 它提供了一种方法,可以将内核数据结构,它们的属性以及它们之间的链接导出到用户空间.sysf ...

  2. hasura graphql 模式拼接demo

    实际上通过上边的介绍,模式拼接和hasura 基本没啥关系了,就是使用graphql-bindings 进行schema 合并了 基本demo 这个是官方提供的demo git clone https ...

  3. coredns 代理consul 运行noamd 部署的应用

    nomad 是一个方便的应用调度平台,consul 一个很不错的服务发现工具,coredns 很不错, 扩展性比较强的dns 服务器,集成起来可能做很强大的事情 我的运行环境是mac,实际情况按需部署 ...

  4. k8s PersistentVolume hostpath 简单使用

    kubernets host PersistentVolume 测试 因为yaml 格式的问题 ,我修改为了json 创建 pv pv.json { "kind": "P ...

  5. MySql登陆密码忘记了 怎么办?

    MySql登陆密码忘记了 怎么办?root密码:连root密码忘记没用root进修改mysql数据库user表咯 root密码: 方法一:MySQL提供跳访问控制命令行参数通命令行命令启MySQL服务 ...

  6. Bootstrap-Plugin:过渡效果(Transition)插件

    ylbtech-Bootstrap-Plugin:过渡效果(Transition)插件 1.返回顶部 1. Bootstrap 过渡效果(Transition)插件 过渡效果(Transition)插 ...

  7. 学习笔记之C++入门到精通(名师教学·手把手教会)【职坐标】_腾讯课堂

    C++入门到精通(名师教学·手把手教会)[职坐标]_腾讯课堂 https://ke.qq.com/course/101465#term_id=100105503 https://github.com/ ...

  8. postman-3http请求

    http消息是服务器和客户端之间交换数据的方式. 有2种类型的消息: 请求:由客户端发送用来触发服务器的动作. 响应:来自服务器的应答. https://developer.mozilla.org/z ...

  9. Java之POI的excel导入导出

    一.Apache POI是一种流行的API,它允许程序员使用Java程序创建,修改和显示MS Office文件.这由Apache软件基金会开发使用Java分布式设计或修改Microsoft Offic ...

  10. ptthon 网络编程

    网络编程 网络目的 : 数据的传输 网络数据传输是一个复杂的过程 ISO :国际标准化组织 OSI 七层模型 --> 网络通信标准化流程 应用层 : 提供用户服务,具体内容由特定程序规定 表示层 ...