概述
本文将先介绍动态规划,再分析矩阵连乘问题,对动态规划了解或者直接想抄算法分析实验报告的小伙伴可选择性的直接跳到下面。
动态规划
1.概念
动态规划(英语: Dynamic programming,简称 DP) 是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
那动态规划算法要表达的核心思想到底是什么?我们来看一个例子
A : "2+2+2+2+2=? 请问这个等式的值是多少? "
B : "计算 ing 。。。。。。结果为 10 "
A : "那如果在等式左边写上 1+ ,此时等式的值为多少? "
B : "quickly 结果为 11 "
A : “你怎么这么快就知道答案了”
A : "只要在 10 的基础上加 1 就行了 "
A : "所以你不用重新计算因为你记住了第一个等式的值为 10 ,动态规划算法也可以说是’记住求过的解来节省时间’
由上可知:动态规划算法的核心就是记住已经解决过的子问题的解;而记住求解的方式有两种:
①自顶向下的备忘录法 ②自底向上。
我们先来看一个最简单的例子,我们曾经求解过的斐波拉契数列 Fibonacci。
public int fib(int n){
if(n <= 1 ){
return 1;
}
if(n == 2){
return 1;
}
return fib(n-1) + fib(n-2);
}
我们分析以前写过的递归就会发现有很多节点被重复执行,如果在执行的时候把执行过的子节点保存起来,后面要用到的时候直接查表调用的话可以节约大量的时间。
2.自顶向下备忘录法
public class Fibonacci {
public static void main(String[] args) {
System.out.println(fibonacci(7));
}
public static int fibonacci(int n) {
if(n<=0)return -1;//合法性判断
//创建备忘录
int[] memo = new int[n+1];
for(int i=0;i<=n;i++) {
memo[i]=-1;
}
return fib(n, memo);
}
/**
* 自顶向下备忘录法
* @param n
* @param memo 备忘录
* @return
*/
public static int fib(int n,int[] memo) {
//如果已经求出了 fib(n)的值直接返回
if(memo[n]!=-1)return memo[n];
//否则将求出的值保存在 memo 备忘录中。
if(n<=2)memo[n]=1;
else {
memo[n]=fib(n-1, memo)+fib(n-2, memo);
}
return memo[n];
}
}
这个方法是由上至下,比如求f(5),我们要求f(4)和f(3),求出来后放入备忘录,当求f(4)时需要f(3)和f(2),我们可以直接从备忘录取f(3)而不是再去求一遍。
3.自底向上的动态规划
备忘录法是利用了递归,上面算法不管怎样,计算 fib(6)的时候最后还是要计算出 fib(1), fib(2), fib(3) ……,那么何不先计算出 fib(1), fib(2), fib(3) ……,呢?这也就是动态规划的核心,先计算子问题,再由子问题计算父问题。
public class FibonacciPlus {
/**
* 自底向上的动态规划
* @param n
* @return
*/
public static int f