本文出自 http://blog.csdn.net/shuangde800
题目链接: 点击打开链接
题目大意
给出一系列的矩阵,给他们取名A ,B…… 并且给出了它们的行数和列数。给完后,给出一系列的表达式,然后要求求出按这些表达式进行计算,会有多少次乘法步骤。
思路
这题去年的暑假是有做过的,在《入门经典》的数据结构专题 ... 打开
现在在看一年前的代码,无论是方法还是代码都觉得不是一般地搓 - -||
在过几个月后看今天写的代码还是会觉得搓吧。
不过这次既然归到了dp专题,那么就用dp的方法来做吧。
(以上是题外话)
很明显看出可以递归求解,而且可转为递推区间dp求解
f(i, j) 表示在(i,j)区间中一共有几次相乘
row(i, j)表示这个区间相乘后的矩形行尺寸
col(i, j) 表示这个区间相乘后的矩形列尺寸
递归时维护这三个数组即可
那么如果str[i]='('且str[j]=')', 就递推求解子问题f(i+1, j-1)
如果只有一边是括号,那么递推求解f(i+1, j) 和 f(i, j-1)
接着枚举终点k, 当这个划分合法时:
f(i, j) = f(i,k) + f(i,k+1) + row(i,k)*row(k+1,j)*col(k+1,j)
代码
/**==========================================
* This is a solution for ACM/ICPC problem
*
* @source:uva-442 Matrix Chain Multiplication
* @type: 记忆化搜索, 区间dp
* @author: shuangde
* @blog: blog.csdn.net/shuangde800
* @email: zengshuangde@gmail.com
*===========================================*/
#include
#include
#include
#include
#include
#include
#include
using namespace std; typedef long long int64; const int INF = 0x3f3f3f3f; const int MAXN = 30; int n; int getRow[150]; int getCol[150]; int f[MAXN][MAXN]; int col[MAXN][MAXN]; int row[MAXN][MAXN]; char str[1000]; bool dfs(int i, int j) { if (f[i][j] != -1) return true; if(i == j) { if( isalpha(str[i])) { row[i][i] = getRow[str[i]]; col[i][i] = getCol[str[i]]; f[i][j] = 0; return true; } return false; } if (str[i]=='(' && str[j]==')') { bool ret = dfs(i+1, j-1); if(!ret) return false; f[i][j] = f[i+1][j-1]; col[i][j] = col[i+1][j-1]; row[i][j] = row[i+1][j-1]; } else if (str[i]=='(' && str[j]!=')'){ bool ret = dfs(i, j-1); if(!ret || col[i][j-1] != getRow[str[j]]) return false; f[i][j] = f[i][j-1] + row[i][j-1] * getRow[str[j]] * getCol[str[j]] ; row[i][j] = row[i][j-1]; col[i][j] = getCol[str[j]]; } else if (str[i]!='(' && str[j]==')') { bool ret = dfs(i+1, j); if(!ret || getCol[str[i]] != row[i+1][j]) return false; f[i][j] = f[i+1][j] + getRow[str[i]] * row[i+1][j] * col[i+1][j]; row[i][j] = getRow[str[i]]; col[i][j] = col[i+1][j]; } for (int k = i; k < j; ++k) { bool ret1 = dfs(i, k); bool ret2 = dfs(k+1, j); if(ret1 && ret2 && col[i][k]==row[k+1][j]) { f[i][j] = f[i][k] + f[k+1][j] + row[i][k] * row[k+1][j] * col[k+1][j]; row[i][j] = row[i][k]; col[i][j] = col[k+1][j]; return true; } } return f[i][j] != -1; } int main(){ scanf("%d", &n); for (int i = 0; i < n; ++i) { char ch[2]; scanf("%s", ch); scanf("%d%d", &getRow[ch[0]], &getCol[ch[0]]); } while (~scanf("%s", str)) { int len = strlen(str); memset(f, -1, sizeof(f)); if (dfs(0, len-1)) { printf("%d\n", f[0][len-1]); } else { puts("error"); } } return 0; }