您的位置:首页 > 编程语言 > C语言/C++

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

2016-12-29 19:11 197 查看

题目

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

例如:

A1[30X35]

A2[35X15]

A3[15X5]

A4[5X10]

A5[10X20]

A6[20X25]

分析

m[1]
=m[1][k] + m[k+1]
+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};//第1、2、3、4、5、6个矩阵行数,第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]
);
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息