计算机算法设计与分析 第3章 动态规划 (笔记)

简介: 计算机算法设计与分析 第3章 动态规划 (笔记)

动态规划和分治法类似,基本思想是将问题划分成若干子问题,先求子问题,然后结合子问题的解得到原问题的解。

与分治法的区别是,使用动态规划的问题 子问题之间不相互独立。 所以用一个表来记录已经解决的子问题答案,避免重复计算。


动态规划算法适用于解最优化问题,通常按照4个步骤设计:

1.找出最优解的性质,并刻画其结构特征;

2.递归地定义其最优值;

3.以自底向上地方式计算最优值;

4.根据计算最优值时得到的信息,构造最优解(如果需要最优解)。


具体的例子:

矩阵连乘问题

问题描述

  给定n个矩阵:A1,A2,...,An,其中Ai与Ai+1是可乘的(i=1,2...,n-1)。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。

1.分析最优解的结构

首先要知道矩阵的基本知识,

矩阵A和矩阵B可乘的条件是A的列数等于B的行数,若A是p*q 矩阵,B是q*r矩阵,则其乘积C=AB是一个p*r的矩阵,

计算次数(乘法次数)是p*q*r次。

我们(通过加括号的方式)改变矩阵乘法的次序,可以改变计算次数。

因此,使得乘法计算次数最少问题就变成了一个如何加括号的问题。

记矩阵连乘积AiAi+1...Aj 为A[i:j]

设这个矩阵在Ak (1<=k<n)处加括号,得到(A1A2...Ak) (Ak+1Ak+2...An)

于是分解成两个规模较小的子问题A[1:K] A[k+1:n]。若要A[1:n]计算次数最少,则子问题A[1:k] A[k+1:n]计算次数也应该最少。

因此,该问题的最优解包含了其子问题的最优解。这种性质称为最优子结构性质。

2. 建立递归关系

m[i][j] = 0, i = j;

        = min { m[i][k] + m[k+1][j] + pi-1pkpj},  i<=k<j,i<j;

3. 计算最优值

这里计算次序可以通过手工画m这张表来找到规律。

 
 
/*
输入参数: 
一维数组p:各矩阵维数
整数n:矩阵个数
二维数组m:存储子问题的最优值
二维数组s:记录最优断开位置(用于得到最优解)
函数功能:生成最优值表m和断开位置表s;
*/
void MatixChain(int *p, int n, int **m, int **s) {
  //先把m这张表的对角线赋值0.
  for (int i = 1; i <= n; i++)
    m[i][i] = 0;
  /*沿对角线方向进行构造m。
   *i是行,j是列,r可以看成是第r条对角线
   *i和j的取值规律是根据对角线变化的规律来的,比如第2条对角线上,i和j相差1,第3条对角线上,i和j相差2
  可以得出第r条对角线上,i和j相差r-1,即 j = i + r-1
  */
  for (int r = 2; r <= n; r++) {
    for (int i = 1; i <= n - r + 1; i++) { 
      int j = i + (r - 1);
      //通过递归式,给m[i][j]赋值
      int k = i;
      m[i][j] = m[i][k]+ m[k + 1][j] + p[i - 1] * p[k] * p[j];
      s[i][j] = k;    
      for (k = i + 1; k < j; k++) {
        int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
        if (t < m[i][j]) {
          m[i][j] = t;
          s[i][j] = k;
        }
      }
    }
  }
 
}

4.构造最优解

void Traceback(int i, int j, int **s) {
  if (i == j)
    return;
  Traceback(i, s[i][j], s);
  Traceback(s[i][j] + 1, j, s);
  cout << "Multiply A" << i << ", " << s[i][j];
  cout << " and A" << (s[i][j] + 1) << ", " << j << endl;
}
/*
注:Multiply A i , s[i][j] and A (s[i][j]+1), j 就
是Ai...A(s[i][j] 和 A(s[i][j]+1)...j相乘
比如Multiply A1, 3 and A4, 6
就是 (A1A2A3) (A4A5A6)
*/

  维数: int p[] = {30,35,15,5,10,20,25};

#include<iostream>
using namespace std;
 
/*
输入参数:
一维数组p:各矩阵维数
整数n:矩阵个数
二维数组m:存储子问题的最优值
二维数组s:记录最优断开位置(用于得到最优解)
函数功能:生成最优值表m和断开位置表s;
*/
void MatrixChain(int *p, int n, int **m, int **s) {
  //先把m这张表的对角线赋值0.
  for (int i = 1; i <= n; i++)
    m[i][i] = 0;
  /*沿对角线方向进行构造m。
   *i是行,j是列,r可以看成是第r条对角线
   *i和j的取值规律是根据对角线变化的规律来的,比如第2条对角线上,i和j相差1,第3条对角线上,i和j相差2
  可以得出第r条对角线上,i和j相差r-1,即 j = i + r-1
  */
  for (int r = 2; r <= n; r++) {
    for (int i = 1; i <= n - r + 1; i++) {
      int j = i + (r - 1);
      //通过递归式,给m[i][j]赋值
      int k = i;
      m[i][j] = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
      s[i][j] = k;
      for (k = i + 1; k < j; k++) {
        int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
        if (t < m[i][j]) {
          m[i][j] = t;
          s[i][j] = k;
        }
      }
    }
  }
 
}
//根据s表生成最优解,使用递归
void Traceback(int i, int j, int **s) {
  if (i == j)
    return;
  Traceback(i, s[i][j], s);
  Traceback(s[i][j] + 1, j, s);
  cout << "Multiply A" << i << ", " << s[i][j];
  cout << " and A" << (s[i][j] + 1) << ", " << j << endl;
}
 
int main()
{
  const int n = 6;
  int p[] = {30,35,15,5,10,20,25};
 
  int **m = new int*[n+1] ;
  int **s = new int*[n+1];
  for (int i = 0; i < n + 1; i++)
  {
    m[i] = new int[n + 1] ;
    s[i] = new int[n + 1];
  }
  for (int i = 1; i < n + 1; i++) {
    for (int j = 1; j < n + 1; j++) {
      m[i][j] =0;
      s[i][j] = 0;
 
    }
  }
 
  
  MatrixChain(p,n,m,s);
  //这里我把构造出来的m表打出来了
  for (int i = 1; i < n + 1; i++) {
    for (int j = 1; j < n + 1; j++) {
      printf("%8d", m[i][j]);
    }
    cout << endl;
  }
  //输出最优解
  Traceback(1, 6, s);
 
  return 0;
} 
相关文章
|
6天前
|
算法
计算机算法设计与分析(1-6章 复习笔记)
计算机算法设计与分析(1-6章 复习笔记)
|
1天前
|
机器学习/深度学习 人工智能 自然语言处理
【机器学习】贝叶斯算法在机器学习中的应用与实例分析
【机器学习】贝叶斯算法在机器学习中的应用与实例分析
7 1
|
3天前
|
算法 Java Go
斐波那契数列是一个非常经典的数学问题,在计算机科学中也经常被用作算法设计和分析的例子。
斐波那契数列是一个非常经典的数学问题,在计算机科学中也经常被用作算法设计和分析的例子。
|
7天前
|
算法 Java 索引
12.12_黑马数据结构与算法笔记Java
12.12_黑马数据结构与算法笔记Java
16 1
|
6天前
|
搜索推荐 算法 前端开发
计算机Java项目|基于协同过滤算法的体育商品推荐系统
计算机Java项目|基于协同过滤算法的体育商品推荐系统
|
1天前
|
机器学习/深度学习 算法 数据可视化
m基于PSO-LSTM粒子群优化长短记忆网络的电力负荷数据预测算法matlab仿真
在MATLAB 2022a中,应用PSO优化的LSTM模型提升了电力负荷预测效果。优化前预测波动大,优化后预测更稳定。PSO借鉴群体智能,寻找LSTM超参数(如学习率、隐藏层大小)的最优组合,以最小化误差。LSTM通过门控机制处理序列数据。代码显示了模型训练、预测及误差可视化过程。经过优化,模型性能得到改善。
15 6
|
1天前
|
算法 调度
基于变异混合蛙跳算法的车间调度最优化matlab仿真,可以任意调整工件数和机器数,输出甘特图
**摘要:** 实现变异混合蛙跳算法的MATLAB2022a版车间调度优化程序,支持动态调整工件和机器数,输出甘特图。核心算法结合SFLA与变异策略,解决Job-Shop Scheduling Problem,最小化总完成时间。SFLA模拟蛙群行为,分组进行局部搜索和全局信息交换。变异策略增强全局探索,避免局部最优。程序初始化随机解,按规则更新,经多次迭代和信息交换后终止。
|
12天前
|
算法
基于GA-PSO遗传粒子群混合优化算法的VRPTW问题求解matlab仿真
摘要: 本文介绍了考虑时间窗的车辆路径问题(VRPTW),在MATLAB2022a中进行测试。VRPTW涉及车辆从配送中心出发,服务客户并返回,需在指定时间窗内完成且满足车辆容量限制,目标是最小化总行驶成本。文章探讨了遗传算法(GA)和粒子群优化(PSO)的基本原理及其在VRPTW中的应用,包括编码、适应度函数、选择、交叉、变异等步骤。同时,提出了动态惯性权重、精英策略、邻域搜索、多种群和启发式信息等优化策略,以应对时间窗限制并提升算法性能。
|
6天前
|
算法 JavaScript 决策智能
基于禁忌搜索算法的TSP路径规划matlab仿真
**摘要:** 使用禁忌搜索算法解决旅行商问题(TSP),在MATLAB2022a中实现路径规划,显示优化曲线与路线图。TSP寻找最短城市访问路径,算法通过避免局部最优,利用禁忌列表不断调整顺序。关键步骤包括初始路径选择、邻域搜索、解评估、选择及禁忌列表更新。过程示意图展示搜索效果。
|
6天前
|
机器学习/深度学习 算法
基于BP神经网络和小波变换特征提取的烟草香型分类算法matlab仿真,分为浓香型,清香型和中间香型
```markdown 探索烟草香型分类:使用Matlab2022a中的BP神经网络结合小波变换。小波分析揭示香气成分的局部特征,降低维度,PCA等用于特征选择。BP网络随后处理这些特征,以区分浓香、清香和中间香型。 ```

热门文章

最新文章