算法导论——动态规划:矩阵连乘

package org.loda.dynamic;

import org.junit.Test;

/**
 * 
* @ClassName: MatrixChainOrder 
* @Description: 矩阵连乘
* 
*  动态规划问题
*  
*  矩阵A1A2...An,求矩阵上述矩阵相乘的效率最高(标量相乘次数最少)的方案,并求出相乘次数
*  
* @author minjun
* @date 2015年5月18日 上午11:12:34 
*
 */
public class MatrixChainOrder {
	
	@Test
	public void testMatrix(){
		//第一个元素表示第一个矩阵的行数,后面的元素表示矩阵的列数
		int[] matrix={30,35,15,5,10,20,25};
		
		int len=matrix.length;
		
		//f[i][j]表示矩阵链Ai....Aj连乘的最优解所需要的连乘次数
		int[][] f=new int[len][len];
		
		//s[i][j]表示矩阵链Ai...Aj连乘的最优切分点为k时k的位置
		int[][] s=new int[len][len];
		
		matrixChainOrder(matrix,f,s);
		
		int i=1,j=6;
		
		System.out.println("矩阵链A"+i+"...A"+j+"最少标量相乘次数为:"+f[i][j]);
		
		//将最优策略打印出来
		System.out.println("最优策略为:");
		printStrategy(s,i,j);
		
	}

	private void printStrategy(int[][] s, int i, int j) {
		if(i>=j){
			//当只有一个矩阵的时候,打印该矩阵
			System.out.print("A"+i);
			return;
		}
		//如果还是一条长度大于1的矩阵链,那么先将需要相乘的部分用括号结合起来
		int k=s[i][j];
		System.out.print("(");
		printStrategy(s, i, k);
		printStrategy(s, k+1, j);
		System.out.print(")");
	}

	private void matrixChainOrder(int[] matrix, int[][] f, int[][] s) {
		
		//矩阵数量
		int n=matrix.length-1;
		
		//i=j表示只有一个矩阵,矩阵链长度为1,无需任何相乘次数,所以为0
		for(int i=1;i<=n;i++){
			f[i][i]=0;
		}
		
		//需要有相乘,那么矩阵链长度至少为2
		for(int len=2;len<=n;len++){
			
			//矩阵链开始位置i
			for(int i=1;i<=n-len+1;i++){
				
				//矩阵链的结束位置j
				int j=i+len-1;
				
				//将该位置的最少相乘次数先初始化为最大值,如果有比他更小的,替换该较小的值
				f[i][j]=Integer.MAX_VALUE;
				
				//最优切分点
				for(int k=i;k<j;k++){
					//利用公式计算f[i][j]所需的相乘次数,如果获取的相乘次数更小,那么就取该值作为f[i][j]最少相乘次数
					int min=f[i][k]+f[k+1][j]+matrix[i-1]*matrix[k]*matrix[j];
					if(min<f[i][j]){
						f[i][j]=min;
						s[i][j]=k;
					}
				}
			}
		}
	}

}

输出结果:

矩阵链A1...A6最少标量相乘次数为:15125
最优策略为:
((A1(A2A3))((A4A5)A6))




转载于:https://my.oschina.net/u/1378920/blog/416438

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值