算法 矩阵连乘 递归+动态规划+备忘录

题目

给定n个矩阵,其中两个相邻的矩阵是可乘的,试求出最佳计算次序,使得总计算量最少。

例如:
A1[30X35]
A2[35X15]
A3[15X5]
A4[5X10]
A5[10X20]
A6[20X25]

分析

m[1][n]=m[1][k] + m[k+1][n] +p0pkpn

代码

1、递归算法

#include <stdio.h> 
#define N 6

int m[N+1][N+1];//最小乘法次数 
int p[N+1]={30,35,15,5,10,20,25};//123456个矩阵行数,第6个矩阵列数.

int digui(int i, int j) {  
    int minvalue =10000000, temp;

    if(i==j) return 0;

    for(int k=i; k<j; k++){  
        temp=digui(i,k) + digui(k+1,j) + p[i-1]*p[k]*p[j];  
        if(temp<minvalue) { 
            minvalue=temp;
            m[i][j]=k;  
        }  
    }   
    return minvalue;  
}  

void traceback(int i,int j) {
    if (i==j)return;
    traceback(i,m[i][j]);
    traceback(m[i][j]+1,j);
    printf("A[%d-%d] and A[%d-%d]\n", i,m[i][j],m[i][j]+1,j);
    return; 
}

int main(){  
    printf("%d\n",digui(1,N));  
    traceback(1,N);
    return 0;  
}  

2、动态规划

#include <stdio.h> 
#define N 6 

int m[N+1][N+1];//m是最优值
int s[N+1][N+1];//s是最优值的断开点的索引
int p[N+1]={30,35,15,5,10,20,25};  

void traceback(int i,int j){  
    if(i==j) return;  
    traceback(i,s[i][j]);  
    traceback(s[i][j]+1,j);  
    printf("A[%d][%d] and A[%d][%d]\n", i,s[i][j],s[i][j]+1,j);  
}  

void dongtai() {  
    int i,j,k,r;   
    for(i=1;i<=N;i++)//单一矩阵的最小乘次都置为0 
        m[i][i]=0;  
    for(r=2;r<=N;r++){//r为连乘矩阵的个数
        for(i=1;i<=N+1-r;i++){ //i表示连乘矩阵中的第一个
            j=i+r-1;  //j表示连乘矩阵中的最后一个
            //所以,这两层循环是起始为Ai,结尾为Aj,长度为r的矩阵段Ai~Aj
            m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];  
            s[i][j]=i;//记录断开点的索引 
            for(k=i+1;k<j;k++){ //循环求出Ai~Aj中的最小数乘次数 
                //在第一个与最后一个之间寻找最合适的断开点,
                //注意,应该从i开始,但是上面已经记录了i。
                int temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];  
                if(temp<m[i][j]){  
                    m[i][j]=temp;  
                    s[i][j]=k;  
                }  
            }  
        }  
    }  
} 

int main(){ 
    dongtai();
    printf("%d\n",m[1][N]);  
    traceback(1,N);  
    return 0;  
}     

3、备忘录

#include <stdio.h> 
#define N 6 

int m[N+1][N+1];//最优解  
int s[N+1][N+1];
int p[N+1]= {30,35,15,5,10,20,25}; 

void traceback(int i,int j){  
    if(i==j) return;  
    traceback(i,s[i][j]);  
    traceback(s[i][j]+1,j);  
    printf("A[%d][%d] and A[%d][%d]\n", i,s[i][j],s[i][j]+1,j);  
}  

int beiwanglu(int i, int j) {  
    if(m[i][j]>0) 
        return m[i][j];  
    if(i==j) 
        return 0;  
    int u=beiwanglu(i,i)+beiwanglu(i+1,j)+p[i-1]*p[i]*p[j];  
    s[i][j]=i;  
    for(int k=i+1; k<j; k++) {  
        int temp=beiwanglu(i,k)+beiwanglu(k+1,j)+p[i-1]*p[k]*p[j];  
        if(temp<u){
            u=temp;  
            s[i][j]=k;  
        }  
    }  
    m[i][j]=u;  
    return u;  
}  

int f(int n){
    int i,j;
    for(i=1; i<=n; i++)  
        for(j=i; j<=n; j++)  
            m[i][j]=0;
    return beiwanglu(1,n);
}
int main() {  
    printf("%d\n",f(N)); 
    traceback(1,N);  
    return 0;  
}  
    原文作者:动态规划
    原文地址: https://blog.csdn.net/plain_maple/article/details/53931512
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞