uvaoj 348 - Optimal Array Multiplication Sequence 构造答案

来源:互联网 发布:淘宝网民族风帽子 编辑:程序博客网 时间:2024/04/18 14:30
uvaoj 348 - Optimal Array Multiplication Sequence
给定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;}


0 0
原创粉丝点击