《算法导论》学习(十八)----动态规划之矩阵链乘(C语言)

这篇具有很好参考价值的文章主要介绍了《算法导论》学习(十八)----动态规划之矩阵链乘(C语言)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本文主要讲解了动态规划中的矩阵链乘问题:给定一个矩阵链,得到它的最小代价计算次序。给出了动态规划方案的分析,并且给出了C语言实现。


一、矩阵链乘

1.问题描述

给定一个n个矩阵的序列(矩阵链) < A 1 , A 2 , A 3 , A 4 , . . . , A n > <A_1,A_2,A_3,A_4,...,A_n> <A1,A2,A3,A4,...,An>,现在我们希望计算它的乘积
A 1 A 2 A 3 A 4 . . . A n A_1 A_2A_3A_4...A_n A1A2A3A4...An
对于矩阵链乘来说,我们可以通过加括号的手段来确定先让哪两个矩阵进行相乘。无论乘的次序如何,最终都不影响结果。
但是不同次序之间的矩阵相乘,计算机所要付出的代价完全不一样。
比如所 < A 1 , A 2 , A 3 > , 其中 A 1 为 2 ∗ 3 ; A 2 为 3 ∗ 4 ; A 3 为 4 ∗ 1 <A_1,A_2,A_3>,其中A_1为2*3;A_2为3*4;A_3为4*1 <A1,A2,A3>,其中A123A234A341
我们可以计算两种不同策略的切割代价:

  • ( ( A 1 A 2 ) A 3 ) = 2 ∗ 3 ∗ 4 + 2 ∗ 4 ∗ 1 = 32 ((A_1A_2)A_3)=2*3*4+2*4*1=32 ((A1A2)A3)=234+241=32
  • ( A 1 ( A 2 A 3 ) ) = 3 ∗ 4 ∗ 1 + 2 ∗ 3 ∗ 1 = 18 (A_1(A_2A_3))=3*4*1+2*3*1=18 (A1(A2A3))=341+231=18

显然,两种代价是完全不一样的。现在我们的问题就是给定一个矩阵链,得到它的最小代价计算次序

二、问题解决

1.最优化的子问题结构

我们先直接给出相应的递归求解公式:
w [ i , j ] = { 0  if  i = j m i n { w [ i , k ] + w [ k + 1 , j ] + p i − 1 p k p j }  if  i < j w[i,j]=\begin{cases} 0& \text{ if }i=j \\ min\{ w[i,k]+w[k+1,j]+p_{i-1}p_kp_j\}& \text{ if } i<j \\ \end{cases} w[i,j]={0min{w[i,k]+w[k+1,j]+pi1pkpj} if i=j if i<j

  • w[i,j]表示第i个矩阵到第j个矩阵,路径上的矩阵链的最小代价
  • p i − 1 p k p j p_{i-1}p_kp_j pi1pkpj代表从最优子解向它的最优父解构造时需要的代价

2.动态规划

我们采用一个二维数组来记录子问题的最优解。比如w[2,4]的最优解就记录在数组w[1,3]种(因为数组从0开始)。
同时我们从长度为2的子矩阵链开始求最优解,之后长度不断加1,直到最后得到n矩阵链的最优解。
这个过程种采用三层循环

  • 第一层循环从小到大遍历矩阵链的长度
  • 第二层循环遍历第一层循环确定长度下的子矩阵链中第一个矩阵的位置
  • 第三层循环遍历前两层循环确定好的矩阵链的全部”切割“方案

3.最优解构造

经过动态规划的三层循环,我们现在可以得到最小的代价的具体值,但是具体的矩阵相乘顺序是如何,我们需要构造最优解。
我们采用一个二维数s组来辅助我们构造出最优方案。

  • 我们用s[0,6]来记录矩阵链w[1,7]第一次加括号的位置,即它的k值。
  • 我们记录全部情况的矩阵链的最优k值。
  • 然后通过递归调用算法,可以得到括号输出结果。具体方案见下方代码。各位读者也可以通过画递归树来迅速确定方案。

三、C代码

1.代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>



//由于有n个矩阵链乘
//需要n+1个存储单元来存储行列信息
//此处SIZE为存储单元的个数
//因此矩阵链乘的个数是SIZE-1 
#define SIZE 10
//此处可以规定矩阵的行列数为1~LIM的随机数 
#define LIM 100
//注意:
//由于计算机存储数大小的限制
//SIZE和LIM不宜过大
//过大肯定会使得程序崩溃 



int Matrix_chain_order(int *p,int s[][SIZE-1],int w[][SIZE-1],int size)
{
	int i=0;
	int j=0;
	int k=0;
	int q=0;
	int l=0;
	int r=0;
	for(i=0;i<size-1;i++)
	{
		w[i][i]=0;
		s[i][i]=0;
	}
	for(i=2;i<=(size-1);i++)
	{
		for(j=1;j<=(size-i);j++)
		{
			l=j;
			r=j+i-1;
			w[l-1][r-1]=10000000;
			for(k=l;k<r;k++)
			{
				q=w[l-1][k-1]+w[k][r-1]+p[l-1]*p[k]*p[r];
				if(q<w[l-1][r-1])
				{
					w[l-1][r-1]=q;
					s[l-1][r-1]=k;
				}
			}
		}
	}
	return w[0][size-2];
}



void print_priority(int s[][SIZE-1],int l,int r)
{
	if(l==r)
	{
		printf("A%d",l+1);
		return;
	}
	printf("(");
	print_priority(s,l,s[l][r]-1);
	print_priority(s,s[l][r],r);
	printf(")");		
}



int main()
{
	int p[SIZE];
	int s[SIZE-1][SIZE-1];
	int w[SIZE-1][SIZE-1];
	int min_pay;
	int i=0;
	int j=0;
	srand((unsigned)time(NULL));
	for(i=0;i<SIZE;i++)
	{
		p[i]=rand()%LIM+1;
	}
	for(i=0;i<SIZE;i++)
	{
		printf("%5d",p[i]);
	}
	printf("\n");
	min_pay=Matrix_chain_order(p,s,w,SIZE);
	printf("%5d\n",min_pay);
	print_priority(s,0,SIZE-2);
	return 0;
} 

2.结果

矩阵连乘问题的动态规划算法c语言,数据结构与算法,算法,动态规划,c语言


总结

文章的不妥之处请各位读者包涵指正。
动态规划的其它问题还可以参考:
《算法导论》学习(十七)----动态规划之钢条切割(C语言)文章来源地址https://www.toymoban.com/news/detail-741922.html

到了这里,关于《算法导论》学习(十八)----动态规划之矩阵链乘(C语言)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《算法导论》学习(四)---- 矩阵乘法的Strassen(斯特拉森)算法

    矩阵乘法可以采用分治的策略。 这里提供了两个分治策略的解决 n ∗ n n*n n ∗ n 矩阵之间乘法的算法 但是着两个方法的缺点是只能是两个 n ∗ n n*n n ∗ n 矩阵的乘法,同时n必须为2的幂 之后也对这两个算法进行了时间复杂度上的分析 对于 n ∗ n n*n n ∗ n 矩阵A,B,C(n为2的

    2023年04月09日
    浏览(47)
  • 算法训练第三十八天|动态规划理论基础、509. 斐波那契数 、70. 爬楼梯 、 746. 使用最小花费爬楼梯

    参考:https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 动态规划是什么 动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。 所以 动态规划中每一个状态一定是由上一个状态推导出来的 ,这一

    2024年02月04日
    浏览(40)
  • 【动态规划】矩阵链乘法——算法设计与分析

    对于矩阵 U p × q U_{ptimes q} U p × q ​ 和 V q × r V_{qtimes r} V q × r ​ , Z p × r = U V Z_{ptimes r}=UV Z p × r ​ = U V ,共需计算 p q r pqr pq r 次标量乘法,时间复杂度为 Θ ( p q r ) Theta (pqr) Θ ( pq r ) 矩阵乘法满足结合律,即 ( U V ) W = U ( V W ) (UV)W=U(VW) ( U V ) W = U ( VW ) ,选择不同的结合

    2024年02月03日
    浏览(65)
  • 矩阵链乘法的动态规划算法_1

    上次我们学习了rod-cutting 问题的动态规划算法,初步了解求解动态规划过程的CRCC步骤,此步骤对于可以运用动态优化的问题非常有用,类似给大家提供了一套思维模板,让我们能更系统的思考和解决问题。本次我们将讨论矩阵链乘法的动态规划算法。 矩阵乘法 在讨论矩阵链

    2024年01月19日
    浏览(52)
  • 算法 矩阵最长递增路径-(递归回溯+动态规划)

    牛客网: BM61 求矩阵的最长递增路径 解题思路: 1. 遍历二维矩阵每个位置,max求出所有位置分别为终点时的最长路径 2. 求某个位置为终点的最长路径时,使用动态规划dp对已经计算出的位置进行记录 3. 处理某个位置的最长路径时,如果dp[i][j]位置已有值,则直接返回即可,否则

    2024年02月07日
    浏览(43)
  • 【动态规划】【 矩阵】【逆向思考】C++算法174地下城游戏

    视频算法专题 动态规划汇总 矩阵 逆向思考 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数

    2024年02月03日
    浏览(46)
  • 动态规划——矩阵优化DP 学习笔记

    前置知识:矩阵、矩阵乘法。 斐波那契数列 在斐波那契数列当中, (f_1 = f_2 = 1) , (f_i = f_{i - 1} + f_{i - 2}) ,求 (f_n) 。 而分析式子可以知道,求 (f_k) 仅与 (f_{k - 1}) 和 (f_{k - 2}) 有关; 所以我们设矩阵 (F_i = begin{bmatrix} f_{i - 1} f_{i - 2} end{bmatrix}) 。 设矩阵 (text{Ba

    2024年02月08日
    浏览(56)
  • 动态规划2:算法考试矩阵连乘问题(超详细手写过程)

                                      更多期末复习笔记欢迎访问我的博客: Miuuu · 语雀​​​​​​​ 动态规划理论基础:(6条消息) 动态规划1:动态规划的入门初学理论基础_黑色柳丁Angel的博客-CSDN博客 矩阵连乘问题是我在算法课接触的第一个动态规划问题

    2023年04月08日
    浏览(40)
  • 最大子矩阵(openjudge noi-2.6基本算法之动态规划-1768)

    来源 OpenJudge - 1768:最大子矩阵 题目描述 已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵。 比如,如下4 * 4的矩阵  0        -2        -7        0  9         2        -6        2 -4      

    2024年04月26日
    浏览(41)
  • 【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II

    视频算法专题 动态规划汇总 矩阵快速幂 滚动向量 【矩阵快速幂】封装类及测试用例及样例 可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符: ‘A’:Absent,缺勤 ‘L’:Late,迟到 ‘P’:

    2024年01月15日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包