题目
给定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};//第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][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;
}