如何从com[][]com[][]com[][]中找到全局最优解?
int cou(int i,int j)
{
if(temp[i][j]>=0)
{
return temp[i][j];
}
if(i==j)
{
temp[i][j]=0;
com[i][j]=0;
return temp[i][j];
}
if(i+1==j)
{
temp[i][j]=r[i]*r[i+1]*r[i+2];
com[i][j]=i;
return temp[i][j];
}
int x=cou(i,i)+cou(i+1,j)+r[i]*r[i+1]*r[j+1];
com[i][j]=i;
int y;
for(int k=i+1;k<j;k++)
{
y=cou(i,k)+cou(k+1,j)+r[i]*r[k+1]*r[j+1];
if(y<x)
{
x=y;
com[i][j]=k;
}
}
temp[i][j]=x;
return temp[i][j];
}
上述代码为求解i到j的局部最优分割点的函数
本题的全局最优解找法:找到1到n间的首个最优分割点k。而后递归的运行函数cou(1,k)和cou(k+1,n);每次运行都将得到的局部最优分割点kik_{i}ki加入记录全局最优解的集合best[]中。
完整代码
#include<iostream>
using namespace std;
int n=4;
int r[100]={0,5,20,50,1,100};//保存矩阵大小
int com[100][100]={0};//保存矩阵编号
int temp[100][100];//保存Mij最优计算量
int cou(int i,int j)
{
cout<<i<<"->"<<j<<endl;
if(temp[i][j]>=0)//已经计算过
{
//因为是从小到大,所以没有覆盖
return temp[i][j];
}
if(i==j)//此时 Mii 也就是同一个矩阵
{
temp[i][j]=0;//所需计算量为0
// com[i][j]=0;//此时分割点,已经在初始化时赋值了
return temp[i][j];
}
if(i+1==j)//两个矩阵相乘 结果固定
{
temp[i][j]=r[i]*r[i+1]*r[i+2];
com[i][j]=i;//此时分割点的下标 是i
return temp[i][j];
}
//其他情况 此时有多个情况
//其中一个选择,作为基准值
int x=cou(i,i)+cou(i+1,j)+r[i]*r[i+1]*r[j+1];//0增益+已知增益+新增增益
com[i][j]=i;//记录这种分割点
int y;
for(int k=i+1;k<j;k++)
{
y=cou(i,k)+cou(k+1,j)+r[i]*r[k+1]*r[j+1];//记录每种选择下的增益
if(y<x)//当前值更优化
{
x=y;
com[i][j]=k;//分割点在k+1
}
}
temp[i][j]=x;//
return temp[i][j];
}
void show(int i,int j)
{
if(i==j)
{
if(i==1)cout<<"M"<<i;
else cout<<"M"<<i;
return ;
}
cout<<"(";
show(i,com[i][j]);
cout<<"*";
show(com[i][j]+1,j);
cout<<")";
}
int main()
{
//初始化
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
temp[i][j]=-1;
com[i][j]=0;
}
}
//调用
cou(1,n);
for(int i=1;i<=n;i++)
{
cout<<endl;
for(int j=1;j<=n;j++)
{
cout<<i<<""<<j<<":"<<com[i][j]<<"\t";
}
}
cout<<endl;
//输出结果 递归
int x=1,y=n;
cout<<"次数:"<<temp[x][y]<<endl;
cout<<"计算顺序:";
show(x,y);
}
2.本题的计算模型及非递归算法的时间复杂度?
计算模型:
mi,j=m_{i,j}=mi,j=000 (i=j)(i=j)(i=j)
mi,j=ri∗ri+1∗ri+2m_{i,j}=r_{i}*r_{i+1}*r_{i+2}mi,j=ri∗ri+1∗ri+2 (j=i+1)(j=i+1)(j=i+1)
mi,j=min(mi,k+mk+1,j+ri∗rk+1∗rj+1)m_{i,j}=min(m_{i,k}+m_{k+1,j}+r_{i}*r_{k+1}*r_{j+1})mi,j=min(mi,k+mk+1,j+ri∗rk+1∗rj+1) (i<=k<j,i<j)(i<=k<j,i<j)(i<=k<j,i<j)
用用用com[][]存储使得mi,j为最小值时的k值存储使得m_{i,j}为最小值时的k值存储使得mi,j为最小值时的k值
非递归代码:
void fei()
{
int n=4;
int r[10]={0,5,20,50,1,100};
int com[10][10]={0};
int m[10][10]={0};
for(int i=1;i<=n;i++)
{
m[i][i]=0;
m[i][i+1]=r[i]*r[i+1]*r[i+2];
com[i][i+1]=i;
}
for(int j=1;j<=n;j++)
{
for(int i=2;i<=n;i++)
{
if(i+j-1>n)continue;
m[j][j+i-1]=m[j][j]+m[j+1][j+i-1]+r[j]*r[j+1]*r[j+i];
com[j][j+i-1]=i;
int temp;
for(int k=j+1;k<=j+i-1;k++)
{
temp=m[j][k]+m[k+1][j+i-1]+r[j]*r[k+1]*r[j+i];
if(temp<m[j][j+i-1])
{
m[j][j+i-1]=temp;
com[j][j+i-1]=k;
}
}
}
}
cout<<endl<<endl<<m[1][n];
for (int i=1;i<=n;i++)
{
cout<<endl;
for (int j=1;j<=n;j++)
cout<<com[i][j];
}
show(1,n);
}
void fun()
{
int n=4;
int r[10]={0,5,20,50,1,100};
int com[10][10]={0};
int m[10][10]={0};
for(int i=1;i<n;i++)
{
m[i][i]=0;
m[i][i+1]=r[i]*r[i+1]*r[i+2];
com[i][i+1]=i+1;
}
for(int s=2;s<n;s++)
{
for(int i=1;i+s<n+1;i++)
{
int j=i+s;
m[i][j]=m[i][i]+m[i+1][j]+r[i]*r[i+1]*r[j+1];
com[i][j] = i;
for (int k=i+1;k<j;k++)
{
int t=m[i][k]+m[k+1][j]+ r[i]*r[k+1]*r[j+1];
if (t <m[i][j])
{
m[i][j] = t;
com[i][j]= k;
}
}
}
}
cout<<endl<<endl<<m[1][n];
for (int i=1;i<=n;i++)
{
cout<<endl;
for (int j=1;j<=n;j++)
cout<<com[i][j];
}
show(1,n);
}
时间复杂度:
函数fei():外层循环n层,内层循环n2层外层循环n层,内层循环n^2层外层循环n层,内层循环n2层 O(n)=n3O(n)=n^3O(n)=n3
同样,函数fun():外层循环n层,内层循环n2层外层循环n层,内层循环n^2层外层循环n层,内层循环n2层 O(n)=n3O(n)=n^3O(n)=n3
T(n)=O(n3)T(n)=O(n^3)T(n)=O(n3)
空间复杂度:
都使用了二维数组 T(n)=O(n2)T(n)=O(n^2)T(n)=O(n2)