动态规划之矩阵链乘法-matrix-chain muliplication problem(dp)

一,问题描述

矩阵链乘法问题(matrix-chain multiplication problem)可描述如下:给定n个矩阵的链<A1,A2,...,An>,矩阵Ai的规模为p(i-1)×p(i) (1<=i<=n),求完全括号化方案,使得计算乘积A1A2...An所需标量乘法次数最少

   因为括号方案的数量与n呈指数关系,所以通过暴力搜索穷尽所有可能的括号化方案来寻找最优方案是一个糟糕策略。


二,代码

如上,此题如果暴力破解的话,就要计算的是每一种括号情况,假如用递归的思想,

那么对于如果要选择a1,a2,利用组合的知识,可以知道可以选出的是n-1种情况。接

下来,将选出的计算结果作为一个整体,那么剩下的(n-1)个矩阵就有n-2中可以选

择的情况。

利用组合排列的知识,可以得到最终暴力破解的次数将会是n(n-1)(n-2)..2*1

这是指数性质的,处理较大的n的时候,这显然不现实。


于是乎就有了动态规划的解法,即从链的长度由小到大的计算每一层,选出每一层的

最小的,参与下一层的计算,这样就免去了很多的重复计算,这也就是动态规划中的

由底向上的方法。


代码如下:

/*矩阵链式乘法*/
#include<iostream>
#include<vector> 
#include<iomanip>

class Solution{
	private:
		int n;                                    //the number of the matrix
		std::vector<int> scale;                   //the scale chain of the matrix,start with i=0
		std::vector<std::vector<int> > cost;            //the cost of every cases,start with (1,1)
		std::vector<std::vector<int> > site;            //the location of the shortest case,start with (1,2)
	public:
		void test();                                    //this function is used th test the application
		void getScale();
		int workCost();
		int showResult(std::vector<std::vector<int> > &c,int i,int j);
};

/*get the scale of the chain*/
void Solution::getScale()
{
	int temp=1;
	std::cout<<"please input the scale of every matric in order:(use 0 to make the end) ";
	while(temp!=0)
	{
	std::cin>>temp;
	if(temp==0) break;
	scale.push_back(temp);
    }
    //l=scale.size();
    n=scale.size()-1;
    
    /*nitialization vector*/ 
    //for(int i=1;i<=n;i++)
    //for(int j=1;j<=n;j++)
    std::vector<std::vector<int> > cost1(n+1,std::vector<int> (n+1));
    std::vector<std::vector<int> > site1(n+1,std::vector<int> (n+1));
    cost=cost1;
    site=site1; 
    
    /*in the question ,if i==j,that mean the two matrix is equal,so the result is 0*/
    /*for(int i=1;i<n;i++)
    cost[i][i]=0;*/
    /*because of the vector's features,so the code is not necessary*/ 
}

/*get the cost and the schme*/
int Solution::workCost()
{
	int j,q;
	//case 1: when the two operands is the same ,that the m[i,i]=0,the work has been done
	
	//case 2:when no same
	for(int l=2;l<=n;l++)               //from the minimum length to be bigger
	  for(int i=1;i<=n-l+1;i++)
	  {
	  	j=i+l-1;
	  	//cost[i][j]=cost[i+1][j]+scale[i-1]*scale[i]*scale[j];
	  	
	  	//to work out in the length of l,wherever the k(site) is ,what the cost is;
	  	for(int k=i;k<=j-1;k++)
	  	{
	  	//	std::cout<<"h ";
		  q=cost[i][k]+cost[k+1][j]+scale[i-1]*scale[k]*scale[j];
		  if (k==i) { cost[i][j]=q;  site[i][j]=k; continue; }
	  	  if(q<cost[i][j])
	  	 {
	  		  cost[i][j]=q;                       //get the lowest cost
	  		  site[i][j]=k;                       //get the site of the "lowest cost"
		  }
	    }
	  }
	  test();
	  /*show the result*/
	  showResult(site,1,n);
}

void Solution::test()
{
	//display the variable
	std::cout<<"VARIABLE IS: ";
	std::cout<<n;
	std::cout<<std::endl;
	 
	//display the scale
	std::cout<<"SCALE IS: ";
	for(int i=0;i<=n;i++)
	std::cout<<scale[i]<<" ";
	std::cout<<std::endl;
	
	//display the cost
	std::cout<<"COST IS: "<<std::endl;
	for(int j=1;j<=n;j++)
	{
	for(int k=1;k<=n;k++)
	std::cout<<std::setw(10)<<cost[j][k]<<" ";
	std::cout<<std::endl;
    }
    std::cout<<std::endl;
	 
	//display the site 
	std::cout<<"SITE IS: "<<std::endl;
	for(int l=1;l<=n-1;l++)
	{
	for(int m=2;m<=n;m++)
	std::cout<<site[l][m]<<" ";
	std::cout<<std::endl;
    }
    std::cout<<std::endl;
}
/*to let you know the answer*/
int Solution::showResult(std::vector<std::vector<int> > &c,int i,int j)
{
	if(i==j) std::cout<<"A["<<i<<"]";
	else {
	std::cout<<'(';
	showResult(site,i,site[i][j]);
	showResult(site,site[i][j]+1,j);
	std::cout<<')';
    }
}

int main()
{
	Solution test;
	test.getScale();
	test.workCost();
	//test.showResult(test.site,1,test.n);
}

测试用例为scale={5,10,3,12,5,50,6};

测试结果为:


猜你喜欢

转载自blog.csdn.net/C_acgl/article/details/79505238