题意:给了许多矩阵,和运算顺序,输出最少计算次数,两矩阵无法相乘,就输出error
思路:栈模拟,遇到矩阵,可以和栈顶的相乘就放进去,无法计算error( '(' 用-1,-1表示),遇到')'就把上一个'('之后的矩阵拿出来DP累加计算数。DP:把题面的ABC相乘,看做50、10、20、5,三个相邻的元素相乘后,消去中间的元素,DP一个长度,枚举中间的位置,推得当前长度最优的情况
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<list>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e5+5;
stack<pii> st;
map<char,int> x,y;
char s[maxn];
int a[1005],tot,dp[1005][1005],ans;
void solve()
{
if(tot < 2) return;
memset(dp,0x3f,sizeof dp);
for(int i = 0; i < tot-1; i++)
dp[i][i+1] = 0;
for(int i = 3; i <= tot; i++)
{
for(int j = 0; j+i-1 < tot; j++)
{
for(int k = j+1; k < j+i-1; k++)
{
dp[j][j+i-1] = min(dp[j][j+i-1],a[j]*a[k]*a[j+i-1] + dp[j][k] + dp[k][j+i-1]);
}
}
}
ans += dp[0][tot-1];
}
int main(void)
{
int n;
while(scanf("%d",&n)!=EOF)
{
x.clear();
y.clear();
for(int i = 1; i <= n; i++)
{
int a,b;
scanf("%s%d%d",s,&a,&b);
x[s[0]] = a;
y[s[0]] = b;
}
while(scanf("%s",s)!=EOF)
{
while(!st.empty()) st.pop();
int flag = 1;
ans = 0;
for(int i = 0; s[i] != '\0'; i++)
{
if(s[i] == '(')
st.push(make_pair(-1,-1));
else if(s[i] == ')')
{
pii b;
tot = 0;
b.second = st.top().second;
b.first = st.top().first;
a[tot++] = b.second;
a[tot++] = b.first;
st.pop();
while(!st.empty() && st.top().first != -1)
{
b.first = st.top().first;st.pop();
a[tot++] = b.first;
}
if(!st.empty() && st.top().first == -1)
st.pop();
solve();
st.push(b);
}
else
{
if(!st.empty() && st.top().second != x[s[i]] && st.top().second != -1)
{
flag = 0;
break;
}
else
st.push(make_pair(x[s[i]],y[s[i]]));
}
}
if(st.size() >= 2)
{
tot = 0;
a[tot++] = st.top().second;
a[tot++] = st.top().first;
st.pop();
while(!st.empty())
{
a[tot++] = st.top().first;st.pop();
}
solve();
}
if(flag)
printf("%d\n",ans);
else
printf("error\n");
}
}
return 0;
}