矩阵连乘之求最优值与构造最优解——呕心沥血篇

2023-05-16

矩阵连乘—详细讲解

初次接触dp,就看到很多位大佬给出自己的见解,dp算是最难的算法之一吧,主要在于灵活度高,需要自己推出动态规划方程

  1. 100个动态规划方程传送门
  2. 涉及到dp问题那么for循环一般从1开始遍历,这样会好些,虽然目前的我还没理解,但是看到许多大佬写代码都是从1开始遍历,那我也慢慢的改变。
下面我就几个问题来说明一下矩阵连乘问题

矩阵连乘问题-求最优值

题目描述
使用动态规划算法求解矩阵连乘问题,输出最少乘法次数。
输入
每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。
输出
矩阵连乘最优计算次数。
样例输入
7
30 35 15 5 10 20 25
样例输出
15125

ps:

刚刚开始拿到这个题目的时候,我很懵逼,看不懂题目的意思,所以我就查资料,之后才明白题目的意思,题目给的输入,其实是一个数组,用来存储矩阵的行和列,输出要输出最少乘法运算
在这里插入图片描述
通过这个表格我们可以直观地了解题目意思,以及得到许多有用的信息

1. 矩阵的个数等于数组长度减一
2. p[0],p[1]代表第一个矩阵的行数和列数,p[1],p[2]代表第二个矩阵的行数和列数…p[5],p[6]代表第六个矩阵的行数和列数



写代码之前我们要得到状态转移方程方程

dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j]);

在这里插入图片描述
我们用三层循环i,j,k分别枚举连乘长度,连乘左边界和划分点

在这里插入图片描述
最后这张图片里面应该保存每次长度的最小值,我们先求出长度为2的有多少种情况,然后把最小的填入表格,再依次求3 4 …6;后面一步都要依赖于前面计算的最小值
代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
int a[maxn], dp[maxn][maxn];
int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        for (int i = 0; i < n; ++i) //从零开始的遍历
            scanf("%d", &a[i]);
        memset(dp, 0, sizeof(dp));               //首先把整个数组初始化
        for (int r = 2; r < n; ++r)              //枚举连乘长度
        {                                        //因为长度为1的矩阵不足以相乘,所以都为0
            for (int i = 1; i < n - r + 1; ++i) //枚举连乘左边界
            {
                int j = i + r - 1;  //枚举连乘又边界
                dp[i][j] = dp[i + 1][j] + a[i - 1] * a[i] * a[j];
                //其实它是 dp[i][j] =dp[i][i](等于0)+ dp[i + 1][j] + a[i - 1] * a[i] * a[j];
                for (int k = i + 1; k < j; ++k)
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + a[i - 1] * a[k] * a[j]); //从不同位置断开取最小值
            }
        }
        printf("%d\n", dp[1][n - 1]); //最后只要找到右上角的数字就是所有矩阵相乘的最小值
    }
    return 0;
}

大佬一般是从1开始遍历,思路都是一样的,就是一些地方需要改动一下

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
int a[maxn], dp[maxn][maxn];
int main()
{
   int n;
   while (~scanf("%d", &n))
   {
      for (int i = 1; i <= n; ++i)
         scanf("%d", &a[i]);
      memset(dp, 0, sizeof(dp));
      for (int r = 2; r < n; ++r)
      {
         for (int i = 1; i < n - r + 1; ++i)
         {
            int j = i + r - 1;
            dp[i][j] = dp[i + 1][j] + a[i] * a[i + 1] * a[j + 1];
            for (int k = i + 1; k < j; ++k)
               dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + a[i] * a[k + 1] * a[j + 1]);
         }
      }
      printf("%d\n", dp[1][n - 1]);
   }
   return 0;
}

简洁明了的代码

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 5;
int a[maxn], dp[maxn][maxn];
int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        for (int l = 2; l < n; ++l)
        { //枚举连乘长度
            for (int i = 1; i + l <= n; ++i)
            {                  //枚举连乘左边界
                int j = i + l; //连乘右边界
                dp[i][j] = inf;
                for (int k = i + 1; k < j; ++k)
                { //枚举划分点
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + a[i] * a[k] * a[j]);
                }
            }
        }
        printf("%d\n", dp[1][n]);
    }
    return 0;
}


矩阵连乘问题-构造最优解

题目描述
使用动态规划算法求解矩阵连乘问题。
输入
每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。
输出
矩阵连乘最优计算次序。
样例输入

7
30 35 15 5 10 20 25

样例输出

A[2:2] * A[3:3]
A[1:1] * A[2:3]
A[4:4] * A[5:5]
A[4:5] * A[6:6]
A[1:3] * A[4:6]

多用一个数组储存每一个区间的最优划分点,递归输出

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
int a[maxn], dp[maxn][maxn], s[maxn][maxn];
void solve(int l, int r)
{
    if (s[l][r]) //查表递归输出
    {
        solve(l, s[l][r]);
        solve(s[l][r], r);
        printf("A[%d:%d] * A[%d:%d]\n", l, s[l][r] - 1, s[l][r], r - 1);
    }
}
int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        for (int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        memset(dp, 0, sizeof(dp));
        for (int l = 2; l < n; ++l)
        {
            for (int i = 1; i + l <= n; ++i)
            {
                int j = i + l;
                dp[i][j] = inf;
                for (int k = i + 1; k < j; ++k)
                {
                    int x = dp[i][k] + dp[k][j] + a[i] * a[k] * a[j];
                    if (dp[i][j] > x)
                    {
                        dp[i][j] = x;
                        s[i][j] = k; //记录最优划分点
                    }
                }
            }
        }
        solve(1, n); //递归输出
    }
    return 0;
}

感觉这个构造法还没理解透,下次理解了再来更新~

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
int a[maxn], dp[maxn][maxn], s[maxn][maxn];
void solve(int l, int r)
{
    if (s[l][r]) //查表递归输出
    {
        solve(l, s[l][r]);
        solve(s[l][r]+1, r);
        printf("A[%d:%d] * A[%d:%d]\n", l, s[l][r], s[l][r]+1, r);
    }
}
int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        for (int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        memset(dp, 0, sizeof(dp));
        for (int l = 2; l < n; ++l)
        {
            for (int i = 1; i + l <= n; ++i)
            {
                int j = i + l-1;
                dp[i][j] = dp[i + 1][j] + a[i] * a[i + 1] * a[j + 1];
                s[i][j] = i;
                for (int k = i + 1; k < j; ++k)
                {
                    int x = dp[i][k] + dp[k + 1][j] + a[i] * a[k + 1] * a[j + 1];
                    if (dp[i][j] > x)
                    {
                        dp[i][j] = x;
                        s[i][j] = k; //记录最优划分点打表
                    }
                }
            }
        }
        solve(1, n-1); //递归输出
    }
    return 0;
}
爱情不是最初的那份轰轰烈烈满眼是你,还有沉寂下来之后共同面对困难的前行。真爱不是遇见而是培养的————截止今日
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

矩阵连乘之求最优值与构造最优解——呕心沥血篇 的相关文章

  • VSC配置C C++

    记录一下配置的过程 xff0c 不然搞完就忘 还会忘记搞事情时的耐心和韧劲 一 GCC 1 下载C语言编译器 链接 xff1a MinGW w64 for 32 and 64 bit Windows Browse Files at Sour
  • Python下实现Tesseract OCR训练字符库(OpenCV-python边缘检测代替jTessBoxEditor手动矫正)

    Python 下实现 Tesseract OCR 训练字符库 xff08 OpenCV 边缘检测代替 jTessBoxEditor 手动矫正 xff09 作者 xff1a 殷越 目录 一 概述二 环境搭建1 下载 Tesseract OCR
  • 【C语言中清空文件的方法】

    C语言清空文件内容 C语言中清空文件的方法 C语言中清空文件的方法 C语言中清空文件的方法很简单 只要以 可写 的方式打开文件 xff0c 就能将这个文件清空 span class token macro property span cla
  • 服务器知识:阿里云ECS实例设置用户root密码、远程连接

    nbsp nbsp nbsp nbsp 阿里云服务器购买之后 新的实例需要设置root登录密码之后才能正常操作 不然就登录不了 重置实例登录密码的时候 适用于在新创建时未设置密码或者忘记密码的情况 对于正在运行的实例 需要在重置实例登录密码
  • 解决chkconfig设置开机启动时出现missing LSB的错误

    0x00 主要原因是脚本不符合LSB tags规范 xff0c 在 bin bash下面添加如下代码即可 以tomcat为例 span class hljs preprocessor BEGIN INIT INFO span span cl
  • 【MinMaxScaler函数】

    会查MinMaxScaler的基本上都应该理解数据归一化 xff0c 本质上是将数据点映射到了 0 1 区间 xff08 默认 xff09 xff0c 但实际使用的的时候也不一定是到 0 1 xff0c 你也可以指定参数feature ra
  • 【forward方法--深度学习】

    1 基本用法 在pytorch中 xff0c 使用torch nn包来构建神经网络 xff0c 我们定义的网络继承自nn Module类 而一个nn Module包含神经网络的各个层 放在 init 里面 和前向传播方式 放在forward
  • 【pycharm查看当前python版本】

    import span class token return type class name sys span span class token function print span span class token punctuatio
  • 【详解Anaconda 、多环境安装多个不同python版本以及根据需要切换python版本】

    前言 本文旨在详细介绍Anaconda 以及 如何在Anaconda上更换python版本 备注 xff1a 根据读者建议 xff0c 这里明确如下 xff1a 标题中的 在Anaconda上更换python版本 实际上是指 xff1a 通
  • PyCharm中多个方法导入包

    一 Python PyCharm和Anaconda的关系 1 Python是一种解释型 面向对象 动态数据类型的高级程序设计语言 虽然Python自带了一个解释器IDLE用来执行 py脚本 xff0c 但是却不利于我们书写调试大量的代码 常
  • 关于pycharm环境和路径配置的介绍

    python解释器路径 python项目解释器路径 用于配置python项目执行的python路径 比如 xff0c 有的项目是运行的是系统python2 7下的环境 xff1b 有的是3 4 xff1b 有的项目使用的是virtualen
  • 【如何快速判断矩阵是否相似对角化】

    快速判断矩阵是否可以相似对角化 关于如何快速判断矩阵是否可以相似对角化的方法 span class token variable span class token variable 96 span 第一步 xff1a 看是不是实对称矩阵 x
  • 【MemoryCompression内存占用过高】

    MemoryCompression内存占用过高 最近笔记本内存 xff08 16G运存 xff09 占用一直在95 43 xff0c cpu占用也在90 43 xff0c 电脑一度无法使用 96 步骤1 96 96 步骤2 96 步骤 96
  • 洛谷 P3366 【模板】最小生成树 (题解+代码)

    题目传送门 xff1a https www luogu com cn problem P3366 题解 xff1a 利用Kruskal算法求解 xff0c 这里大致说下Kruskal算法 对于一个点数为n的生成树而言 很显然 xff0c 想
  • WSL_03 WSL2 从C盘迁移到D盘

    文章目录 1 动机1 查看虚拟机状态 xff0c 并关闭要迁移的虚拟机2 迁移WSL22 1 出现的问题 xff1a 已存在具有提供的名称的分发 已解决 3 设置启动时的默认用户 xff0c 没有设置默认为root参考 1 动机 WSL2默
  • iOS开发:Block传值的运用

    在iOS开发中传值是一个非常经典的方法 有六种传值方式 属性传值 代理传值 Block传值 方法传值 单例传值 通知传值 本章就来分享一下通过Block完成两个不同界面间的传值操作 首先再来了解一下Block 简单一点说 Block就是一段
  • Ubuntu 安装 CUDA and Cudnn

    文章目录 0 查看 nvidia驱动版本1 下载Cuda2 下载cudnn参考 xff1a 0 查看 nvidia驱动版本 nvidia smi 1 下载Cuda 安装之前先安装 gcc g 43 43 gdb 官方 xff1a https
  • 傻傻分不清楚:裸纤、专线、SDH、MSTP、MSTP+、OTN、PTN、IP-RAN

    著作权归作者所有 xff1a 来自51CTO博客作者51CTOsummer的原创作品 xff0c 如需转载 xff0c 请注明出处 xff0c 否则将追究法律责任 xff08 一 xff09 裸纤 裸纤也叫裸光纤 xff0c 运营商提供一条
  • github下载慢的两种解决方式

    1 修改配置文件 cmd ping github com会显示超时 我们只需要绕过dns域名解析就行 打开DNS查询网站http tool chinaz com dns xff0c 搜索github com的域名解析服务 xff0c 选择一
  • ModuleNotFoundError: No module named ‘cv2‘解决办法

    xff08 linux系统 xff09 这里记录一个实验过程中碰到的bug xff1a 我是在linux系统上面使用conda环境 xff0c 且已经下载了opencv python xff0c 但在python文件中import cv2仍

随机推荐

  • mybatis-plus + PageHelper

    一 导入相关依赖 span class token operator lt span span class token operator span span class token operator span mysql 驱动包 span
  • 阿里云端口问题-配置完安全组无效

    Centos7 X安全组配置完成后仍不能访问 xff0c 此时要配置防火墙放行端口才行 使用以下命令打开端口 tcp udp 两种传输层模式 add port 61 端口号 firewall cmd zone 61 public add p
  • Anaconda教程——Ubuntu 平台

    Anaconda 使用教程 Ubuntu 平台 说明 xff1a 对应着 Python 有 2 x 版本和 3 x 版本 xff0c Anaconda 也有 Anaconda2 以及 Anaconda 3 两个版本 xff0c 考虑其流行度
  • ubuntu突然上不去网

    今天ubuntu突然上不去网了 xff08 昨天还行 xff0c 就很神奇 xff09 在一篇博客中找到了解决办法 xff0c 里面给出了三种解决办法 xff0c 详见原文连接 我用的第二种 xff0c 很简单 xff0c 亲测有效 记录下
  • 原理篇1、锂电池充/供电与电量检测

    目录 1 充电 供电电路2 电量检测电路3 电量计算4 关于IIR滤波器设计参考资料资料获取 1 充电 供电电路 键盘上的充电电路原理图 数据手册中的原理图 其中与TP5400 3脚 PROG 连接的电阻用来设置充电电流大小 电阻大小与充电
  • git 配置用户名与邮箱(git篇)

    配置使用 Git 仓库的人员姓名 span class token function git span config span class token parameter variable global span user name spa
  • 华为2288H V5服务器iBMC 安装windows server服务器

    公司有一台2288H V5服务器 xff0c 需要重装 xff0c IT的人走了 xff0c 只能自己去安装了 xff0c 去机房 xff0c 发现已经设置好了iBMC xff0c IP已经和公司网络连在一起 xff0c 可以直接在自己办公
  • 木棒加工问题(贪心+动态规划)

    问题描述 现有n根木棒 xff0c 已知它们的长度和重量 xff0c 要用一部木工机一根一根地加工这些木棒 该机器在加工过程中需要一定的准备时间 xff0c 是用于清洗机器 xff0c 调整工具和模板的 木工机需要的准备时间如下 xff1a
  • 清翔51单片机开发板及原理图-去年购买的

    2019年购买了清翔的51单片机开发板 xff0c 然后开始学习单片机编程及开发 xff0c 学习到2020年7月份 xff0c 基本上学习的差不多了 xff0c 现在开始我要开始写博客了 之前的维修博客暂停
  • 51单片机——蜂鸣器按照次数响起1.0

    写的不知道好不好 xff0c 有什么不对的地方还请指出 xff0c 谢了 本次使用了do while xff0c 听说比单独的while循环速度快 xff0c 具体也不太清楚 xff0c 就按照别人说的了 且蜂鸣器每次响1秒 xff0c 响
  • MCU BSP Driver分层设计

    最近在摸索和学习中发现 xff0c 可以对于MCU驱动使用分层设计思想 这样的设计避免应用层 用户层和功能层直接去操作寄存器了 所有寄存器的操作均在 通用设备驱动层 xff0c 这个层是直接控制MCU的寄存器 哦 xff0c 驱动层里面忘记
  • 基于STM32F10X的GPIO驱动

    完善我的文章 MCU BSP Driver分层设计 xff0c 本次提供GPIO控制驱动 本片完成了GPIO控制驱动操作 本人是基于野火指南者STM32开发板 本驱动基于STM32F10X官方固件库 主程序 int main void WH
  • 基于STM32F10X的GPIO驱动V0.1

    基于上篇 基于STM32F10X的GPIO驱动 增加GPIO的操作功能 xff0c 并且优化提高部分函数效率 最重要的添加了未带操作 xff0c 这样就可以高效的控制GPIO了 3 未解决的问题 xff1a 当前我无法将WHT GPIO P
  • CPU供电(路由器)万用表测量“短路”现象分析

    在维修路由器产品时发现CPU供电1 1V对地阻值50 100 之间 xff0c 在用万用表的蜂鸣档测量时会报 短路 xff0c 本以为是cpu或者供电芯片损坏 xff0c 原来我测量好板子也是这个现象 xff0c 故这个1 1 V cpu供
  • Lenovo ThinkPad T450s更换WiFi模块、指纹模块、维修SD卡针

    本电脑2015年8月份购买的 xff0c 2018年4月份之后开始出现问题 xff0c 首先指纹很难开机 xff0c 很难录入 xff0c 然后就是SD卡不知道什么时候无法使用了 xff0c 由于笔记本不常完也就没太注意 xff0c 最近有
  • 2.4G&5G WiFi 5V供电大短路,维修更换5G芯片

    故障类别 xff1a 无WiFi信号 故障现象 xff1a 漏电 xff0c 无2 4G和5GWiFi 故障描述 xff1a 开机后发现电流比其它板子大一点 xff0c 并且无异常发热情况 附件 xff1a 分析过程 xff1a 根据故障找
  • 路由器不开机——维修更换MT7621AT CPU

    故障类别 xff1a 不开机 故障现象 xff1a 210mA横流不开机 故障描述 xff1a 发现CPU异常发烫不开机 xff0c 其它地方未有发热现象 附件 xff1a 原因分析 xff1a 开机测量各路电压 xff0c 发现均有电压
  • 编译QT 5.9.7 msvcr2013 x86 32位版本

    因为项目需要 xff0c 用到了qt msvcr2013 x86 版本 但是官方下载的qt安装包里面只有x64的 xff0c 因此决定自己编译x86的版本 编译所需要的工具 xff1a qt源码包 xff0c python xff0c vs
  • <C语言>打印 n 阶魔方阵( n 为奇数),魔方阵的每一行、每一列和对角线元素之和都相等

    打印魔方阵 xff0c 首先我们得知道魔方阵的编写规律 xff1a 魔方阵的填充规律如下 xff1a 假设当前创建了一个矩阵 span class token keyword int span matrix span class token
  • 矩阵连乘之求最优值与构造最优解——呕心沥血篇

    矩阵连乘 详细讲解 初次接触dp xff0c 就看到很多位大佬给出自己的见解 xff0c dp算是最难的算法之一吧 xff0c 主要在于灵活度高 xff0c 需要自己推出动态规划方程 100个动态规划方程传送门涉及到dp问题那么for循环一