矩阵连乘问题(贪心)
Posted ALLap
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵连乘问题(贪心)相关的知识,希望对你有一定的参考价值。
矩阵的乘积:一个i行j列的矩阵和一个j行k列的矩阵相乘,计算次数为i*j*k
那么问题来了:给定n个可相乘的矩阵,怎么相乘才能是计算次数最少呢?
输入:
多组输入数据。
每组数据以N开始,表示矩阵链的长度。接下来一行N+1个数表示矩阵的行/列数。
1<=N<=300
输出:
对于每组样例,输出一行最少运算次数的方案,每两个矩阵相乘都用“()”括起来,详见样例
如果存在多种解决方案,最终输出结果选取先计算左边的矩阵,详见Hint
输入样例:
3
10 30 5 60
3
10 20 5 40
输出样例:
((A1A2)A3)
((A1A2)A3)
解法:
用p[i]表示第i个矩阵的列/p[i-1]表示第i个矩阵的行,关键在于对一段长矩阵链中找到一个分割点。并用s[ ][ ]记录分割点,便于最后的输出。
状态:m[i][j]表示第i个矩阵到第j个矩阵乘积的最小值
状态转移:m[i][j]=min{m[i][k-1]+m[k][j]+p[i-1]*p[k-1]p[j](i+1<=k<=j)}//这里把第k个矩阵归为后半部分,同时由于优先计算左边的,所以我们从右边往左边找断点。
1 #include<iostream> 2 using namespace std; 3 const int num=302; 4 int matrix_chain(int p[], int n, int m[num][num], int s[num][num]) 5 { 6 int i,j,r,k; 7 for (r = 2; r <= n; r++) //r为连乘矩阵的个数 8 { 9 for (i = 1; i <= n-r+1; i++) 10 { 11 j = i + r -1; 12 m[i][j] = 9999999; 13 for (k = j; k >= i+1; k--)//从右边开始找断点 14 { 15 int tmp = m[i][k-1] + m[k][j] + p[i-1]*p[k-1]*p[j]; 16 if (tmp < m[i][j]) 17 { 18 m[i][j] = tmp; 19 s[i][j] = k; 20 } 21 } 22 } 23 } 24 return m[1][n]; 25 } 26 27 void print_chain(int i, int j, int a[],int s[num][num]) 28 { //递归的方式来把最小乘数的表达式输出 29 if (i == j) 30 { 31 printf("A%d",a[i]); 32 } 33 else 34 { 35 printf("("); 36 print_chain(i,s[i][j]-1,a,s); 37 print_chain(s[i][j],j,a,s); 38 printf(")"); 39 } 40 } 41 42 int main() 43 { 44 int n; 45 int min_num; 46 int p[num]={0}; 47 int a[num]={0}; 48 int m[num][num]={0}, s[num][num]={0}; 49 while(cin>>n) 50 { 51 52 for(int t=0;t<=n;t++) 53 cin>>p[t]; 54 for(int k=1;k<=n;k++) 55 a[k]=k;//用于给矩阵标号便于输出 56 min_num = matrix_chain(p,n,m,s); 57 print_chain(1,n,a,s); 58 cout<<"\n"; 59 } 60 system("pause"); 61 return 0; 62 }
以上是关于矩阵连乘问题(贪心)的主要内容,如果未能解决你的问题,请参考以下文章