动态规划(矩阵连乘)

题目描述:
给定n个矩阵{A1,A2,…,An},其中,Ai与Ai+1是可乘的,(i=1,2 ,…,n-1)。用加括号的方法表示矩阵连乘的次序,不同的计算次序计算量(乘法次数)是不同的,找出一种加括号的方法,使得矩阵连乘的次数最小。

例如:

              A1是A(5*10)的方阵;

              A2是A(10*100)的方阵;

              A3是A(100*2)的方阵;

那么有两种加括号的方法:

(A1A2)A3;
A1(A2A3);

 第一种方法的计算量:5*10*100+5*100*2=6000;

 第二种方法的计算量:10*100*2+5*10*2=2100;

 可以看出不同计算方法计算量差别很大。

问题分析:

  • 矩阵连乘的条件:第一个矩阵的列等于第二个矩阵的行,此时两个矩阵是可乘的;
  • 多个矩阵连乘的结果矩阵,其行列等于第一个矩阵的行和最后一个矩阵的列;
  • 两个矩阵相乘的计算量:

例如:A(3*2),B(2*4)
可知总执行次数为:3*2*4=24.
所以矩阵Am*n和Bn*k的乘法运算次数为:m*n*k;

思路

现给出数组p[] = { 30, 35, 15, 5, 10, 20, 25 },其中第0个数是第一个矩阵的行数,第一个到第六个分别为六个矩阵的列数
在这里插入图片描述
动态规划实现(自己写的,但是步骤基本一致)(时间复杂度较低)

public class matrixMultiply {
	public static void main(String[] args) {
		int p[] = { 30, 35, 15, 5, 10, 20, 25 };
		int[][] m = new int[p.length][p.length];
		int[][] s = new int[p.length][p.length];
		multiply(m,s,p);
		for (int i = 0; i < m.length; i++) {
			for (int j = 0; j < m[0].length; j++) {
				System.out.print(m[i][j]+"\t");
			}
			System.out.println();
		}
		System.out.println();
		for (int i = 0; i < s.length; i++) {
			for (int j = 0; j < s[0].length; j++) {
				System.out.print(s[i][j]+"\t");
			}
			System.out.println();
		}
	}

	private static void multiply(int[][] m, int[][] s, int[] p) {
		for (int r = 3; r <= p.length; r++) {	//链长(从3开始)
			for (int begin = 0; begin <= p.length-r; begin++) {	//链开始位置
				int end = begin+r-1;	//链结束位置
				int temp1 = 0;	//记录begin到end的链连乘的最少次数
				int temp2 = 0;	//记录练成次数最少时k的值
				for (int k = begin+1; k <= end-1 ; k++) {	//遍历分割位置k
					m[begin][end] = m[begin][k]+m[k][end]+p[begin]*p[end]*p[k];	//计算时使用以前计算出的比现在的begin到end短的链的最少连乘次数
					if(k==begin+1){
						temp1=m[begin][end];	//赋初值
						temp2 = k;
					}else{
						if(temp1>m[begin][end]){	//获取连乘次数最少
							temp1 = m[begin][end];	
							temp2 = k;
						}
					}
				}
				m[begin][end] = temp1;
				s[begin][end] = temp2;
			}
		}
	}
}

迭代实现(时间复杂度较高)

public class matrixMultiply {
	static int p[] = { 30, 35, 15, 5, 10, 20, 25 };	//这是六个矩阵的横纵长度,第0个数是第一个矩阵的行数,1到6分别是第1到第6个矩阵的列数
	public static void main(String[] args) {
		System.out.println(getMatrixChain(0, 6));
	}
	public static int getMatrixChain(int i, int j) {
		int min = 0;
		if (j-i<=1) {	//链长小于或等于2时都返回0
			return 0;
		}
		for (int r = i+1; r <= j-1; r++) {	//r代表分割位置
			int time = getMatrixChain(i, r) + getMatrixChain(r , j)	//以r作为分界线将数组分为两部分
					+ p[i] * p[r] * p[j];	//分割位置r处的乘法次数
					//然后把r位置前的运算次数和r后的运算次数和r位置的运算次数加在一起即为总次数
			if (r == i+1) {	//给min赋初值
				min = time;
			}
			if (min > time) {
				min = time;
			}
		}
		return min;
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值