动态规划之矩阵链
以前大佬写的
//矩阵链
//时间复杂度为O(N^3)
/*划分子问题:
1、确定子问题的边界: 每一个子问题就是矩阵链的长度,边界即矩阵链长度
2、将问题求解变成多步判断的过程:找出子问题的最优解即 矩阵链中求出最小计算量
定义优化函数:
q=min{q,m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]}
设计备忘录:m[i][j]=q
设计标记函数:s[j][j]=k(k是括号位置)
*/
#include<iostream>
using namespace std;
const int INT_MAX=2147483647;
int const M=6;//矩阵个数
void MATRIX_CHAIN_ORDER(int *p,int Length,int m[][M],int s[][M])
{
int q,n=Length-1;
for(int i=1;i<=n;i++) m[i][i]=0;
for(int l=2;l<=n;l++) //l为链长
{
for(int i=1;i<=n-l+1;i++) //i为左边界
{
int j=i+l-1; //j为右边界
m[i][j]=INT_MAX;
for(int k=i;k<=j-1;k++) //k为划分点
{
q=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]; //q为矩阵i和j之间可能计算的次数
if(q<m[i][j]) //更新记录
{
m[i][j]=q;//m[i][j]为矩阵i和j之间最小的计算次数
s[i][j]=k;
}
}
}
}
}
void PRINT_OPTIMAL_PARENS(int s[][M],int i,int j)
{
if(i == j) cout<<"A"<<i;
else
{
cout<<"(";
PRINT_OPTIMAL_PARENS(s,i,s[i][j]);
PRINT_OPTIMAL_PARENS(s,s[i][j]+1,j);
cout<<")";
}
}
int main()
{
int p[M]={4,5,3,6,4,5};//矩阵行列数
int m[M][M],s[M][M];//m中存储矩阵i和j之间最小的计算次数,s记录矩阵i和j中在哪个地方加括号,两者均为备忘录
MATRIX_CHAIN_ORDER(p,M,m,s);
cout<<"当n=5时最优解为: \n"<<m[1][5];
cout<<"\n括号化方案为:\n";
PRINT_OPTIMAL_PARENS(s,1,5);
return 0;
}
自己悟
#include<iostream>
using namespace std;
#define N 6//六个矩阵
#define INT_MAX 2147483647
int b[N][N];
int m[N]={4,5,3,6,4,5};
/*
过程就是从底层出发,
先求出矩阵链长度为2时的各个次数,
接着求出长度分别为3、4、5、6时的次数
对于每一个长度,我们只添加一个括号
子问题就是矩阵链的长度
b[1][5] =min(b[1][k]+b[k+1][5]+...)
*/
void matrixChain()
{
int num;
for(int i=0;i<N;i++) b[i][i]=0;
for(int length=2;length<=N;length++){//矩阵链的长度是2~6
for(int i=1;i<=N-length;i++){ //i是左边界
int j = i+length-1; //j是右边界
b[i][j]=INT_MAX;
//下面的循环就是求minb[i][k]+b[k+1][j]+mk-1*....
for(int k=i;k<j;k++){ //k是括号的位置
num=b[i][k]+b[k+1][j]+m[i-1]*m[k]*m[j];
b[i][j]=num<b[i][j]?num:b[i][j];
}
}
}
}
int main()
{
matrixChain();
cout<<b[1][5];
return 0;
}
一些错误的代码
/*void matrixChain()
{
int num;
for(int i=1;i<N;i++)
b[i][i]=0;
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
b[i][j]=INT_MAX;
for(int k=i;k<j;k++){
num=b[i][k]+b[k+1][j]+m[i]*m[k+1]*m[j+1];
b[i][j]=num<b[i][j]?num:b[i][j];
}
}
}
}
*/
/*void matrixChain()
{
int num;
for(int i=0;i<N;i++) b[i][i]=0;
for(int i=0;i<N;i++){
for(int length=2;length<N;l++){
int j=i+length-1;
m[i][j]=INT_MAX;
for(int k=i;k<=j-1;k++){
sum=b[i][k]+b[k+1][j]+m[i]*m
}
}
}
}
这段代码错误的原因是子问题界定错误*/
推广一下
其实矩阵链问题和平面凸多边形最优三角划分问题相似,不过求的权函数不是相乘了,而是相加。

浙公网安备 33010602011771号