题目连接:348 - Optimal Array Multiplication Sequence
题目大意:给出n个矩阵, 每个矩阵有它的行和列, 现在要计算这n个连续的矩阵的乘积, 要求找出计算量最小的方案, 每两个矩阵相乘的计算量为(a.l * a.r * b.r),然后生成一个a.l和b.r的矩阵。
解题思路:典型的区间dp, 只不过在每次找最优解之后要记录当前区间的最优分解点rec[a][b]。
#include <stdio.h>
#include <string.h>
const int N = 105;
struct state {
int l;
int r;
}tmp[N];
int n, dp[N][N], rec[N][N];
void Init() {
memset(dp, 0, sizeof(dp));
memset(rec, 0, sizeof(rec));
for (int i = 0; i < n; i++)
scanf("%d%d", &tmp[i].l, &tmp[i].r);
}
int solve(int a, int b) {
if (dp[a][b]) return dp[a][b];
if (a == b) return 0;
if (a + 1 == b) return dp[a][b] = tmp[a].l * tmp[a].r * tmp[b].r;
int now, Max = 1 << 30;
for (int i = a; i < b; i++) {
now = solve(a, i) + solve(i + 1, b) + tmp[a].l * tmp[i].r * tmp[b].r;
if (now < Max) {
Max = now;
rec[a][b] = i;
}
}
dp[a][b] = Max;
return Max;
}
void print(int a, int b) {
if (a == b)
printf("A%d", a + 1);
else if (a + 1 == b)
printf("(A%d x A%d)", a + 1, b + 1);
else {
printf("(");
print(a, rec[a][b]);
printf(" x ");
print(rec[a][b] + 1, b);
printf(")");
}
}
int main() {
int cas = 1;
while (scanf("%d", &n), n) {
Init();
solve(0, n - 1);
printf("Case %d: ", cas++);
print(0, n - 1);
printf("\n");
}
return 0;
}