您的位置:首页 > 其它

矩阵连乘问题 C语言实现

2015-11-12 22:22 232 查看
矩阵连乘问题.

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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: