算法分析实验之矩阵链乘法

一、问题分析

 

矩阵链乘法问题
给定一个n个矩阵的序列〈A1,A2,A3...An〉〈A1,A2,A3...An〉,我们要计算他们的乘积:A1A2A3...AnA1A2A3...An,由于矩阵乘法满足结合律,加括号不会影响结果,但是不同的加括号方法,算法复杂度有很大的差别:
考虑矩阵链:〈A1,A2,A3〉:〈A1,A2,A3〉,三个矩阵规模分别为10×100、100×5、5×5010×100、100×5、5×50
如果按((A1A2)A3)((A1A2)A3)方式,需要做10∗100∗5=500010∗100∗5=5000次,再与A3A3相乘,又需要10∗5∗50=250010∗5∗50=2500,共需要7500次运算:
如果按(A1(A2A3))(A1(A2A3))方式计算,共需要100∗5∗50+10∗100∗50=75000100∗5∗50+10∗100∗50=75000次标量乘法,具有10倍的差别。可见一个好的加括号方式,对计算效率有很大影响。
为了得到所需乘法次数最少的方案,需要计算所有种方案的代价。
对一个n个矩阵的链,令P(n) 表示可供选择的括号化方案的数量。
完全括号化方案的矩阵乘积可以描述为两个完全括号化的部分相乘的形式,
P(n)=1P(n)=1 , n=1n=1
P(n)=∑n−1k=1P(k)P(n−k)P(n)=∑k=1n−1P(k)P(n−k), n≥2n≥2
k为分割点,即第k个矩阵和第k+1个矩阵之间

可以考虑动态规划来求解

 

二、递归式

 

Ai…j:表示矩阵链相乘的子问题AiAi+1…Aj;
M[i…j]:表示得到乘积Ai…j所用的最少基本运算次数;
假设,最后一次相乘发生在矩阵链Ai…k和Ak+1…j之间,即AiAi+1…Aj=(AiAi+1)(Ak+1Ak+2…Aj)k=i,i+1,…,j-1

public class MatrixChain {
    private int array[][];
    private int p[];
    private int s[][];

    public MatrixChain(){

        p=new int[]{3,5,2,1,10};
        array=new int[4][4];
        s=new int[4][4];

        p=new int[]{2,7,3,6,10};
        array=new int[4][4];
        s=new int[4][4];

        p=new int[]{10,3,15,12,7,2};
        array=new int[5][5];
        s=new int[5][5];

        p=new int[]{7,2,4,15,20,5};
        array=new int[5][5];
        s=new int[5][5];
    }
    /**动态规划*/
    public void martixChain(){
        int n=array.length;
        for(int i=0;i<n;i++){
            array[i][i]=0;//初始化0
        }
        for(int r=2;r<=n;r++){  		//不同规模的子问题两个矩阵相乘
            for(int i=0;i<=n-r;i++){    //每一个规模为r的矩阵连乘序列的首矩阵Ai
                int j=i+r-1;  			//每一个规模为r的矩阵连乘序列的尾矩阵Aj
                // 决策为k=i的乘法次数
                array[i][j]=array[i+1][j]+p[i]*p[i+1]*p[j+1];
                s[i][j]=i;
                for(int k=i+1;k<j;k++){ //对Ai...Aj的所有决策,求最优值,记录最优决策
                    int t=array[i][k]+array[k+1][j]+p[i]*p[k+1]*p[j];
                    if(t<array[i][j]){
                        array[i][j]=t;
                        s[i][j]=k;
                    }
                }
            }
        }
    }
    /*
     * 待求矩阵为:Ai...Aj
     */
    public void traceBack(int i ,int j){
        if(i<j){
            traceBack(i,s[i][j]);
            traceBack(s[i][j]+1,j);
            if(i==s[i][j] && (s[i][j]+1)==j){
                System.out.println("把A"+(i+1)+"到A"+(j+1)+"括起来");
            }else if(i==s[i][j] && (s[i][j]+1)!=j){
                System.out.println("把A"+((s[i][j]+1)+1)+"到A"+(j+1)+"括起来,在把A"+(i+1)+"到A"+(j+1)+"括起来");
            }else if(i!=s[i][j] && (s[i][j]+1)==j){
                System.out.println("把A"+(i+1)+"到A"+(s[i][j]+1)+"括起来,在把A"+(i+1)+"到A"+(j+1)+"括起来");
            }else{
                System.out.println("把A"+(i+1)+"到A"+(s[i][j]+1)+"括起来,在把A"+((s[i][j]+1)+1)+"到A"+(j+1)+"括起来,然后把A"+(i+1)+"到A"+(j+1)+"括起来");
            }
        }
    }
    public static void main(String[] args) {
        MatrixChain m=new MatrixChain();
        m.martixChain();
        System.out.println("结果1:");
        m.traceBack(0, 3);
        System.out.println("结果2:");
        m.traceBack(0, 3);
        System.out.println("结果3:");
        m.traceBack(0, 4);
        System.out.println("结果4:");
        m.traceBack(0, 4);
    }

}
//嵌套循环需要O(n)3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值