完全加括号的矩阵连乘积

 


设有四个矩阵   A、B、C、D         ,它们的维数分别是:A=50*10   B=10*40  c=40*30   D=30*5

总共有五中完全加括号的方式

完全加括号的矩阵连乘积_第1张图片

 

 

由此可知我们直接穷举是不行的,复杂度是取决于维数的规模,现在我们可以知道   我们要的是找到其中维数乘积最小的两个,这里我们可以用普通的思维   找乘积最小的。也就是  找子问题最小的,这里我们可以看到最小的是

CD     再是B(CD)   

这也正好符合动态规划的思想    将待解决的问题分解成诺干个子问题,先求子问题,然后从这些子问题的解   递归 得到原问题的解。

与分治不同的是,适合于动态规划求解的问题,经分解得到的子问题往往不是相互独立的。诺用分治来解决这类问题,则分解得到的子问题太多,以至于最后解决原问题时间需要耗指数级时间。

矩阵的维数为pi-1*pi;

 

状态方程是:    0                                                                  i=j

                         min { m[i][k] + m[k+1][j] + p[i-1] * p[i] * p[k]}  i<j

                        i<=k<j


void MatricChain(int *p,int n,int **m,int **s)
{
     for (int i=1; i<=n; i++)
     {
         m[i][i]=0;//i=j的情况下, 
     }
     for (int r=2; r<=n; r++)
     {
         for (int i=1; i<=n-r+1; i++)//为什么i<=n-r+1,是这样的,比如A1A2A3A4A5,r=2,那么i是不是最多到A4的位置,也就是最多到n-r+1的位置 
         {
             int j=r+i-1;
             m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];// m[i][i]=0
也就是i=k情况             s[i][j]=i;
             for (int k=i; k<j; i++)
             {
                 int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
                 if (t<m[i][j])
                 {
                    m[i][j]=t;
                    s[i][j]=k;           
                 }
             }
         }
     } 
}

 

 

 

然后调用TraceBack(1,4,s)就可得到最用计算次序
void TraceBack(int i, int j, int **S)
{
     if (i==j) 
         break;
     TraceBack(i,s[i][j],s);
     TraceBack(s[i][j]+1,j,s);
     cout<<"Multiply A"<<i<<","<<s[i][j];
     cout<<"and A"<<s[i][j]+1<<","<<j<<endl;
}

 

 

测试 没写  ,读者可以拷贝这里的代码看下
 

你可能感兴趣的:(c,测试)