矩阵连乘问题
矩阵连乘问题
Time Limit:500MS Memory Limit:65536K
Total Submit:191 Accepted:121
Description
给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2 ,…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。
Input
输入包含多组测试数据。第一行为一个整数C,表示有C组测试数据,接下来有2*C行数据,每组测试数据占2行,每组测试数据第一行是1个整数n,表示有n个矩阵连乘,接下来一行有n+1个数,表示是n个矩阵的行及第n个矩阵的列,它们之间用空格隔开.
Output
你的输出应该有C行,即每组测试数据的输出占一行,它是计算出的矩阵最少连乘积次数.
Sample Input
1 3 10 100 5 50
Sample Output
7500
第一种是dp
#include <iostream>
using namespace std;
const int N = 1000;
int p[N], m[N][N];
int n;
void MatrixChain()
{
int i, j, k, t;
////////此为初始化底层,即一个矩阵的情况///////////
for(i = 1; i <= n; i++)
m[i][i] = 0;//赋值为0,是因为1个矩阵需做0次相乘
for(int r = 2; r <= n; r++)
{//计算r个矩阵连乘的情况
for(i = 1; i <= n - r + 1; i++)
{//计算从i个矩阵开始的连续r个矩阵相乘的最少次数
j = i + r - 1;//A[i : j],连续r个矩阵
////////////以下为其中一种情况,断开点i,即第一个矩阵独立/////////////////
m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
////////////////开始寻找最优值///////////////////////
for(k = i + 1; k < j; k++)
{
t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if( t < m[i][j])
m[i][j] = t;
}
}
}
}
int main()
{
int C;
while(cin>>C)
{
while(C-- && cin>>n)
{
for(int i = 0; i <= n; i++)
cin>>p[i];
MatrixChain();
cout<<m[1][n]<<endl;
}
}
return 0;
}
using namespace std;
const int N = 1000;
int p[N], m[N][N];
int n;
void MatrixChain()
{
int i, j, k, t;
////////此为初始化底层,即一个矩阵的情况///////////
for(i = 1; i <= n; i++)
m[i][i] = 0;//赋值为0,是因为1个矩阵需做0次相乘
for(int r = 2; r <= n; r++)
{//计算r个矩阵连乘的情况
for(i = 1; i <= n - r + 1; i++)
{//计算从i个矩阵开始的连续r个矩阵相乘的最少次数
j = i + r - 1;//A[i : j],连续r个矩阵
////////////以下为其中一种情况,断开点i,即第一个矩阵独立/////////////////
m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
////////////////开始寻找最优值///////////////////////
for(k = i + 1; k < j; k++)
{
t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if( t < m[i][j])
m[i][j] = t;
}
}
}
}
int main()
{
int C;
while(cin>>C)
{
while(C-- && cin>>n)
{
for(int i = 0; i <= n; i++)
cin>>p[i];
MatrixChain();
cout<<m[1][n]<<endl;
}
}
return 0;
}
第二种是备忘录
#include <iostream>
using namespace std;
const int N = 1000;
int p[N], m[N][N];
int n;
int LookupChain(int i, int j);
int MemoizedMatrixChain()
{
/*
备忘录方法为每个子问题建立一个记录项,初始化时,该记录存入个特殊值,表示该
子问题尚未解决。
*/
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
m[i][j] = 0;
return LookupChain(1, n);//解A[1 : n]矩阵连乘
}
int LookupChain(int i, int j)
{//解A[i : j]
if(m[i][j] > 0)
return m[i][j];//此为子问题已经解决的情况
if(i == j)
return 0;//此为底层
int u, t, k;
//初始为 A[i : i] * A[i + 1 : j]
m[i][j] = LookupChain(i, i) + LookupChain(i + 1, j) + p[i - 1] * p[i] * p[j];
for(k = i + 1; k < j; k++)
{
t = LookupChain(i, k) + LookupChain(k + 1, j) + p[i - 1] * p[k] * p[j];
if( t < m[i][j])
m[i][j] = t;
}
return m[i][j];
}
int main()
{
int C;
while(cin>>C)
while(C-- && cin>>n)
{
for(int i = 0; i <= n; i++)
cin>>p[i];
cout<<MemoizedMatrixChain()<<endl;
//cout<<m[1][n]<<endl;
}
return 0;
}
using namespace std;
const int N = 1000;
int p[N], m[N][N];
int n;
int LookupChain(int i, int j);
int MemoizedMatrixChain()
{
/*
备忘录方法为每个子问题建立一个记录项,初始化时,该记录存入个特殊值,表示该
子问题尚未解决。
*/
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
m[i][j] = 0;
return LookupChain(1, n);//解A[1 : n]矩阵连乘
}
int LookupChain(int i, int j)
{//解A[i : j]
if(m[i][j] > 0)
return m[i][j];//此为子问题已经解决的情况
if(i == j)
return 0;//此为底层
int u, t, k;
//初始为 A[i : i] * A[i + 1 : j]
m[i][j] = LookupChain(i, i) + LookupChain(i + 1, j) + p[i - 1] * p[i] * p[j];
for(k = i + 1; k < j; k++)
{
t = LookupChain(i, k) + LookupChain(k + 1, j) + p[i - 1] * p[k] * p[j];
if( t < m[i][j])
m[i][j] = t;
}
return m[i][j];
}
int main()
{
int C;
while(cin>>C)
while(C-- && cin>>n)
{
for(int i = 0; i <= n; i++)
cin>>p[i];
cout<<MemoizedMatrixChain()<<endl;
//cout<<m[1][n]<<endl;
}
return 0;
}