ZOJ 1276 "Optimal Array Multiplication Sequence"(最优矩阵链乘问题+区间DP)
•题意
矩阵 A(n×m) 和矩阵 B(m×k) 相乘,共做 n×m×k 次乘法运算;
给你 n 个矩阵,求这 n 个矩阵的最优结合方式,使得做的总乘法运算次数最少;
•题解
定义dp(i,j)表示第[i,...j]个矩阵的最小的乘法运算次数;
定义d(i,j)表示第[i,...j]个矩阵的最优解从d(i,j)分开,即(Ai×Ai+1×......×Ad(i,j))×(Ad(i,j)+1×......×Aj);
求解dp(i,j)的时候,求出最优解,并记录是从那个位置分开使得其最优;
输出时递归输出即可;
•Code
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 const int maxn=100; 5 6 int n; 7 int p[maxn]; 8 int dp[maxn][maxn]; 9 int d[maxn][maxn]; 10 11 void DP() 12 { 13 for(int len=2;len <= n;++len) 14 { 15 for(int i=1,j=i+len-1;j <= n;++i,++j) 16 { 17 for(int k=i;k < j;++k) 18 { 19 int cur=dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j]; 20 if(dp[i][j] > cur) 21 { 22 d[i][j]=k; 23 dp[i][j]=cur; 24 } 25 } 26 } 27 } 28 } 29 void Print(int l,int r) 30 { 31 if(l == r) 32 { 33 printf("A%d",l); 34 return ; 35 } 36 if(l > r) 37 return ; 38 39 printf("("); 40 Print(l,d[l][r]);///[l,r]在d[l][r]处分割 41 printf(" x "); 42 Print(d[l][r]+1,r); 43 printf(")"); 44 } 45 void Solve() 46 { 47 for(int i=0;i <= n;++i) 48 for(int j=0;j <= n;++j) 49 dp[i][j]=(i == j ? 0:INF); 50 DP(); 51 Print(1,n); 52 printf("\n"); 53 } 54 int main() 55 { 56 int kase=1; 57 while(~scanf("%d",&n) && n) 58 { 59 for(int i=1;i <= n;++i)///第i个矩阵的行和列为p[i-1],p[i] 60 { 61 int a,b; 62 scanf("%d%d",&a,&b); 63 p[i-1]=a; 64 p[i]=b; 65 } 66 printf("Case %d: ",kase++); 67 Solve(); 68 } 69 return 0; 70 }