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

 1 #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 }
View Code

 

posted @ 2019-06-14 08:41  HHHyacinth  阅读(202)  评论(0编辑  收藏  举报