动态规划之矩阵链

以前大佬写的

//矩阵链  
//时间复杂度为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
			}
		}
	}
}   
这段代码错误的原因是子问题界定错误*/

推广一下

其实矩阵链问题和平面凸多边形最优三角划分问题相似,不过求的权函数不是相乘了,而是相加。

posted @ 2020-03-23 16:20  南理工学渣  阅读(43)  评论(0)    收藏  举报