标签:
题目传送门
1 /*
2 题意:加上适当的括号,改变计算顺序使得总的计算次数最少
3 矩阵连乘积问题,DP解决:状态转移方程:
4 dp[i][j] = min (dp[i][k] + dp[k+1][j] + p[i-1] * p[k] * p[j]) (i<=k<j)
5 s[i][j] 记录断开的地方(即加括号的位置),回溯法输出结果
6 */
7 #include <cstdio>
8 #include <cstring>
9 #include <string>
10 #include <algorithm>
11 #include <cmath>
12 #include <iostream>
13 using namespace std;
14
15 const int MAXN = 1e2 + 10;
16 const int INF = 0x3f3f3f3f;
17 int dp[MAXN][MAXN];
18 int s[MAXN][MAXN];
19 int p[MAXN];
20 int n;
21
22 void print(int i, int j)
23 {
24 if (i == j) printf ("A%d", i);
25 else
26 {
27 printf ("(");
28 print (i, s[i][j]);
29 printf (" x ");
30 print (s[i][j] + 1, j);
31 printf (")");
32 }
33 }
34
35 void work(void)
36 {
37 for (int i=1; i<=n; ++i) dp[i][i] = 0;
38 for (int l=2; l<=n; ++l)
39 {
40 for (int i=1; i<=n-l+1; ++i)
41 {
42 int j = i + l - 1;
43 dp[i][j] = INF;
44 for (int k=i; k<=j-1; ++k)
45 {
46 int tmp = dp[i][k] + dp[k+1][j] + p[i-1] * p[k] * p[j];
47 if (tmp < dp[i][j])
48 {
49 dp[i][j] = tmp; s[i][j] = k;
50 }
51 }
52 }
53 }
54
55 print (1, n); puts ("");
56 }
57
58 int main(void) //ZOJ 1276 Optimal Array Multiplication Sequence
59 {
60 //freopen ("ZOJ_1276.in", "r", stdin);
61
62 int cas = 0;
63 while (scanf ("%d", &n) == 1)
64 {
65 if (n == 0) break;
66 for (int i=1; i<=n; ++i) scanf ("%d%d", &p[i-1], &p[i]);
67
68 printf ("Case %d: ", ++cas);
69 work ();
70 }
71
72 return 0;
73 }
74
75 /*
76 Case 1: (A1 x (A2 x A3))
77 Case 2: ((A1 x A2) x A3)
78 Case 3: ((A1 x (A2 x A3)) x ((A4 x A5) x A6))
79 */
矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4490772.html