矩阵连乘(动态规划非递归)

对于矩阵连乘机问题就不概述了,主要是找出最佳的结合方式使得整个式子的运算次数最少。

对于这个问题之所以用动态规划的原因点如下:

第一:由于矩阵连乘机本身可以划分为若干个子矩阵链连乘机,而且若干个子矩阵链的最优解组合起来就是原矩阵链的最优解。

第二:对于原矩阵链的不同划分中个子问题是存在重叠子问题。

所以当此问题用动态规划算法来解决时就会变得很简单,算法的精髓就是从子问题入手、自底向上一步一步的由子问题的最优解去找到更复杂的大问题的最优解,

当循环到原问题时得出即为原为题的最优解;而且在自底向上的过程中应该将各个子问题的解记录在一张表中,以避免之后重复的去计算同一个子问题。个人觉得自底

向上的去记录子问题的解避免重复计算,这是动态规划最大的一个亮点了,不然就和递归分治策略本质上没有太大的区别了。

#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;

/*
*矩阵连乘(动态规划非递归)
*/
vector<vector<int>> m;//m[i][j]表示矩阵Ai连乘到Aj的最少运算次数
vector<vector<int>> s;//s[i][j]记录矩阵Ai和矩阵Aj之间的分割点

//计算该连乘式子的最佳结合方式
void MatrixChain(vector<int>& p)
{
	int n = p.size()-1;//一共有n个矩阵相乘
	m = vector<vector<int>>(n+1,vector<int>(n+1,0));//0行0列空余
	s = vector<vector<int>>(n+1,vector<int>(n+1,0));//0行0列空余
	//初始化m数组
	for(int i = 0;i<=n;i++) m[i][i] = 0;
	for(int d = 2;d<=n;d++)//自底向上填表、d:表示矩阵连乘的距离值
		for (int i = 1; i <= n-d+1; i++)//i表示Ai矩阵
		{
			int j = i+d-1;
			//计算m[i][j]
			int k = i+1;
			m[i][j] = p[i-1]*p[i]*p[j]+m[k][j];
			s[i][j] = i;
			for ( k++; k<j ; k++)
			{
				int ini = m[i][k] +p[i-1]*p[k]*p[j]+m[k+1][j];
				if(ini<m[i][j])
				{
					m[i][j] = ini;
					s[i][j] = k;
				}
			}
		}
}

//输出该连乘式子的最佳结合方式
void PrintMatrixChain(int n,int m)
{
	if(n==m)
	{
		cout<<"A"<<n;
		return;
	}
	int k = s[n][m];
	if(n==k)
		PrintMatrixChain(n,k);
	else
	{
		cout<<"(";
		PrintMatrixChain(n,k);
		cout<<")";
	}
	if(k+1==m)
		PrintMatrixChain(k+1,m);
	else
	{
		cout<<"(";
		PrintMatrixChain(k+1,m);
		cout<<")";
	}
}
int main()
{
	vector<int> vec;
	copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(vec));
	MatrixChain(vec);
	PrintMatrixChain(1,vec.size()-1);
}

运行测试:

输入六个矩阵分别为:A1(50*10)  A2(10*40)  A3(40*30)  A4(30*5)  A5(5*20)  A6(20*15)

计算A1*A2*A3*A4*A5*A6

输出的最佳结合方式为:如下图

时间: 2024-11-10 00:41:20

矩阵连乘(动态规划非递归)的相关文章

Best Coder Round#25 1003 树的非递归访问

虽然官方解释是这题目里的树看作无向无环图,从答案来看还是在“以1作为根节点”这一前提下进行的,这棵树搭建好以后,从叶节点开始访问,一直推到根节点即可——很像动态规划的“自底向上”. 但这棵树的搭建堪忧:给出的边不知道哪边更接近根节点.所以我给出的方案干脆在两个顶点都将对方加成孩子,等到访问的时候再作处理,根据从1这个根节点开始访问这个特性,额外加一个“isVisited"来做区分. 然后利用栈对树进行非递归访问 /** * For best-coder problem 3 */ #include

递归与非递归及其相互转换

一.什么是递归 递归是指某个函数直接或间接的调用自身.问题的求解过程就是划分成许多相同性质的子问题的求解,而小问题的求解过程可以很容易的求出,这些子问题的解就构成里原问题的解了. 二.递归的几个特点 1.递归式,就是如何将原问题划分成子问题. 2.递归出口,递归终止的条件,即最小子问题的求解,可以允许多个出口. 3.界函数,问题规模变化的函数,它保证递归的规模向出口条件靠拢 三.递归的运做机制 很明显,很多问题本身固有的性质就决定此类问题是递归定义,所以递归程序很直接算法程序结构清晰.思路明了.

斐波拉契数列的递归、非递归、公式法多种方法实现

实现斐波拉契数列:1,1,2,3,5,8...,当n>=3时,f(n)=f(n-1)+f(n-2). 解:求解斐波拉契数列方法很多,这里提供了4种实现方法和代码,由于第5种数学公式方法代码太过繁琐,只做简单介绍 方法一:递归调用,每次递归的时候有大量重复计算,效率低,可将其调用的过程转化成一颗二叉树进行分析,二叉树的总结点个数不超过(2^n-1)个,由于其是不完全二叉树,那么函数计算的次数必小于(2^n-1),时间复杂度为O(2^n):递归调用的深度为n,空间复杂度为O(n) 方法二:非递归数组

九度OJ—题目1205:N阶楼梯上楼问题 (非递归)

题目描述: N阶楼梯上楼问题:一次可以走两阶或一阶,问有多少种上楼方式.(要求采用非递归) 输入: 输入包括一个整数N,(1<=N<90). 输出: 可能有多组测试数据,对于每组数据, 输出当楼梯阶数是N时的上楼方式个数. 样例输入: 4 样例输出: 5 来源: 2008年华中科技大学计算机保研机试真题 答疑: 解题遇到问题?分享解题心得?讨论本题请访问:http://t.jobdu.com/thread-7928-1-1.html 基本思路: 走到第n阶时可能是从第n-1阶走一步到的,也可能

数据结构基础 背包问题(一) 之 非递归解

[问题描述] "背包题目"的基本描述是:有一个背包,能盛放的物品总重量为S,设有N件物品,其重量分别为w1,w2,-,wn,希望从N件物品中选择若干物品,所选物品的重量之和恰能放进该背包,即所选物品的重量之和即是S.递归和非递归解法都能,试非递归算法求得"背包题目"的一组解 [算法分析] 1.此程序是得到问题的所有解: 2.本题只对背包有重量约束: 3.算法思想(暴力枚举) 1)初始化flag数组,数组长度为背包数目 n,数组为全 0 序列,0,1表示是否添加第 i

台阶问题引出的递归和非递归的思考

一个台阶总共有n级,如果一次可以跳1级,也可以跳2级.求总共有多少总跳法,并分析算法的时间复杂度. 如果看到过这个题目的童鞋们,可能很快就有思路了,这个属于动态规划的典型题目. 基本思路如下: 假设n个台阶共有f(n)个跳法.那么我第一步可以跳1级,可以跳2级. 如果第一步跳1级,那么之后我有f(n-1)种跳法. 如果第一步跳2级,那么之后我有f(n-2)中跳法. 所以,得到下面的公式 一看到这个公式,很多人就会想到Finbonacci队列(兔子繁殖问题),很多人都是通过这个例子学会的递归方法.

斐波那契数列的递归和非递归解法

//递归解法 function fib(n){ if(n < 1){ throw new Error('invalid arguments'); } if(n == 1 || n == 2){ return 1; } return fib(n - 1) + fib(n - 2); } //非递归解法 function fib(n){ if(n < 1){ throw new Error('invalid arguments'); } if(n == 1 || n == 2){ return 1

用递归和非递归的方法输出斐波那契数列的第n个元素(C语言实现)

费波那契数列(意大利语:Successione di Fibonacci),又译为费波拿契数.斐波那契数列.费氏数列.黄金分割数列. 在数学上,费波那契数列是以递归的方法来定义: {\displaystyle F_{0}=0} {\displaystyle F_{1}=1} {\displaystyle F_{n}=F_{n-1}+F_{n-2}}(n≧2) 用文字来说,就是费波那契数列由0和1开始,之后的费波那契系数就是由之前的两数相加而得出.首几个费波那契系数是: 0, 1, 1, 2, 3

8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化

上两篇博客 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现 研究了递归方法实现回溯,解决N皇后问题,下面我们来探讨一下非递归方案 实验结果令人还是有些失望,原来非递归方案的性能并不比递归方案性能高 代码如下: package com.newflypig.eightqueen; import java.util.Date; /** * 使用循环控制来实现回溯,解决N皇后 * @author [email pr