给定n个矩阵的序列,求出使得矩阵乘法的运算量最小的运算方法,输出格式见样例。在枚举i到j的位置k的时候,记录最优的这个k就可以了,所以要用另外一个数组来存储这个k。得出来后,递归的构造答案就行了,当只有一个矩阵的时候输出,否则就从k位置断开,递归构造。递归写起来方便。这个数组记录的是绝对的位置k。可以在构造的时候直接打印答案,不用保存。做这道题目的时候遇到了十分奇葩的问题,最神奇的是还不知道是什么原因。
代码如下:
/*************************************************************************
> File Name: 348.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2014年11月16日 星期日 12时12分27秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
#define N 15
//pre[i][j]记录第i个矩阵到第j个矩阵相乘最优的绝对位置
int w[N], dp[N][N], pre[N][N], n;
//先短区间,后长区间
void solve(void)
{
for (int i = 0; i < n; ++i) {
for (int j = 1; j + i <= n; ++j) {
dp[j][j + i] = (i == 0) ? 0 : INF;
//dp[j][j + i] = (i == 0) ? 0 : INT_MAX;
//刚开始在这里,pre不初始化或者初始化为j,就AC,初始化
//为其他的就RE,不知道是什么原因。pre[i][j+i]当i为0时,
//在后边构造答案的时候就没有用到,其他的一定会被覆盖,
//所以说,初始化为任何值都是可以的,但是不知道什么原因。
//后来想到INF可能不够大,就换成了INT_MAX,竟然AC了,
//可是如果INF不够大的话,怎么会在使用INF的时候,并且
//不初始化的时候AC呢?我真是搞不懂了。
//pre[j][j + i] = j;
//pre[j][j + i] = (i == 0) ? 0 : j;
//pre[j][j + i] = 0;
for (int k = j; k < j + i; ++k) {
int tmp = dp[j][k] + dp[k + 1][j + i]
+ w[j - 1] * w[k] * w[j + i];
if (dp[j][j + i] > tmp) {
dp[j][j + i] = tmp;
pre[j][j + i] = k;
}
}
}
}
}
//构造最优解,当只有一个矩阵时,应该直接打印
void getans(int l, int r)
{
if (l > r) {
return;
} else if (l == r) {
printf("A%d", l);
} else {
int k = pre[l][r];
printf("(");
getans(l, k);
printf(" x ");
getans(k + 1, r);
printf(")");
}
}
int main(int argc, char *argv[])
{
int c = 0;
while (scanf("%d", &n) != EOF) {
if (n == 0) {
break;
}
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &w[i - 1], &w[i]);
}
printf("Case %d: ", ++c);
solve();
getans(1, n);
printf("\n");
}
return 0;
}