矩阵连乘问题 C语言实现

矩阵连乘问题.

eg.A1 A2 A3 A4 A5 A6,    已知:各矩阵的维数:A1=30*35,A2=35*15,A3=15*5,A4=5*10,A5=10*20, 则  int p[]={30,35,15,5,10,20,25};
    A5=20*25 .隐含的条件是:两矩阵必须是相邻两个才能乘.求六个矩阵求其加括号的位置,从而使得连乘的次数最少.

解:思想:矩阵连乘用动态规划发求解的两个原因:

    1.矩阵连乘问题的最优解包含着其中子问题的最优解.

                2.在计算最优值的过程中,许多子问题被重复计算.
       用A[i,j]来表示[Ai..Aj]加括号的位置.则有A[1,1]表示的给一个数组加括号的位置,0,同理也有A[I,I]=0;
       假设我们将A[i,i+1...k,k+1,..,j]中间k的位置加括号,则有乘法的次数为:

       A[I,I+1,...K]的乘法次数 + A[K+1,...J]乘法次数 + A[I,I+1...]*A[K+1...J]的次数

  

    1.首先数组P={30,35,15,5,10,20,25},下表从0开始,6结束.
    2.用二维数组m[i][j]表示最少乘法次数,s[i][j]表示当m[i][j]为最小时加括号的位置.


下面代码

//用来得到最优解的m[][] ,s[][];
void MatrixChain(int p[6] ,int n, int m[][7] ,int s[][7]){
        int r = 0;    //当前参与矩阵连乘的元素的个数
        int i = 0;    //记录其实下标
        int j = 0;    //记录终止下标
        int k = 0;    //表示当前还有的加括号
        int t = 0;    //交换

        for(i = 1; i <= n; i++)
                m[i][i] = 0;                //当只有一个矩阵时,乘法次数是0
        for(r = 2; r <= n; r++ )              //至少是两个矩阵参与连乘,最多有n个  
                for(i = 1; i <= n-r+1; i++){              //i<n-r+1,表示当R=3时,第一下标最多是4,才能组成(A4 A5 A6)保证其是三个.
                        j = i + r -1;                     //当起始下标和个数确定之后,终止下标是固定的
                        m[i][j] = m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];        //都默认从起始下标之后加第一个括号,即当作从第一个断开得到初始值
                        s[i][j] = i;    
                        for(k = i+1; k < j; k++){            //从第二层循环开始,也就是当r>2时,还会有j-i种加括号的方法
                                t = m[i][k] + m[k+1][j] + p[i-1]* p[k] *p[j];
                                if(t < m[i][j]){          //如果这j-i中方法里还有比第一种方法小的,就交换.
                                        m[i][j] = t;
                                        s[i][j] = k ;
                                }
                        }
                }

}

void TrackBack(int i ,int j, int s[][7]){          //从i=1,j=6开始.
        if(i==j) return ;
        TrackBack(i,s[i][j],s);                //递归的看第一个断开位置之前的    
        TrackBack(s[i][j]+1,j,s);           //第一次断开位置之后的.
        printf("A%d",i);
        printf(" and A%d",j);
        printf("\n");

}


int main(){
        int n = 6;
        int p[]={30,35,15,5,10,20,25};           //p用来存放每一个矩阵的行数
        int s[7][7] = {0};
        int m[7][7] = {0};
        MatrixChain(p,n,m,s);
        TrackBack(1,n,s);
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值