UVA442栈


1)原题代码1

#include<cstdio>
#include<stack>
#include<iostream>
#include<string>

using namespace std;
const int maxn=103;
struct sta{
    int a;
    int b;
    sta(int a=0,int b=0):a(a),b(b) {}
}z[maxn];
stack<sta>s;//可以将结构体直接压入栈,而不是将结构体中某个变量作为标志入栈
int main()
{
    int num;
    cin>>num;
    for(int i=0;i<num;i++){
        string name;
        cin>>name;
        int name_num=name[0]-'A';//直接对应序号就不用为新合成的矩阵起名而烦恼,序号依次递增即可
        cin>>z[name_num].a>>z[name_num].b;
    }
    string exp;//用string而不用getchar()可以省去很多麻烦

    while(cin>>exp){
        int g=26;
        int sum=0;int bj=1;
        int len=exp.length();
        for(int i=0;i<len;i++){
            if(isalpha(exp[i])){//遇到字母入栈,或者新和成的结构体也直接入栈
                s.push(z[exp[i]-'A']);
            }
            else if(exp[i]==')'){//遇到')'出栈,遇到'('不用管
                sta z2=s.top();s.pop();
                sta z1=s.top();s.pop();
                if(z1.b!=z2.a){
                    bj=0;
                    break;
                }
                z[g].a=z1.a;z[g].b=z2.b;//z[g++].a=z1.a;z[g++].b=z2.b;之前两次g++当然要错了!!
                s.push(z[g]);
                g++;
                sta ztemp=s.top();
                sum+=(z1.a*z1.b*z2.b);
            }
        }
        if(bj)
            cout<<sum<<endl;
        else
            cout<<"error"<<endl;
        //memset(z,)
    }
    return 0;
}
2)原题代码2

#include<cstdio>
#include<stack>
#include<iostream>
#include<string>
using namespace std;

struct sta {
  int a, b;
  sta(int a=0, int b=0):a(a),b(b) {}//构造函数,结构体与类再这一点是相似的
} z[26];

stack<sta> s;

int main() {
  int num;
  cin >> num;
  for(int i = 0; i < num; i++) {
    string name;
    cin >> name;
    int name_num = name[0] - 'A';
    cin >> z[name_num].a >> z[name_num].b;
  }
  string exp;
  while(cin >> exp) {
    int len = exp.length();
    int bj = 1;
    int sum = 0;
    for(int i = 0; i < len; i++) {
      if(isalpha(exp[i])) s.push(z[exp[i] - 'A']);
      else if(exp[i] == ')') {
        sta z2 = s.top(); s.pop();
        sta z1 = s.top(); s.pop();
        if(z1.b != z2.a) { bj=0; break; }
        s.push(sta(z1.a, z2.b));<span style="font-family: Arial, Helvetica, sans-serif;">//这是什么?222</span>
        sum += (z1.a * z1.b * z2.b);

      }
    }
    if(bj)
        cout<<sum<<endl;
    else
        cout<<"error"<<endl;
  }

  return 0;
}

3)原题

Suppose you have to evaluate an expression like A*B*C*D*E where A,B,C,D and E are matrices. Since matrix multiplication is associative, the order in which multiplications are performed is arbitrary. However, the number of elementary multiplications needed strongly depends on the evaluation order you choose.

For example, let A be a 50*10 matrix, B a 10*20 matrix and C a 20*5 matrix. There are two different strategies to compute A*B*C, namely (A*B)*C and A*(B*C).

The first one takes 15000 elementary multiplications, but the second one only 3500.

Your job is to write a program that determines the number of elementary multiplications needed for a given evaluation strategy.

Input Specification

Input consists of two parts: a list of matrices and a list of expressions.

The first line of the input file contains one integer n ( tex2html_wrap_inline28 ), representing the number of matrices in the first part. The next n lines each contain one capital letter, specifying the name of the matrix, and two integers, specifying the number of rows and columns of the matrix.

The second part of the input file strictly adheres to the following syntax (given in EBNF):

SecondPart = Line { Line } <EOF>
Line       = Expression <CR>
Expression = Matrix | "(" Expression Expression ")"
Matrix     = "A" | "B" | "C" | ... | "X" | "Y" | "Z"

Output Specification

For each expression found in the second part of the input file, print one line containing the word "error" if evaluation of the expression leads to an error due to non-matching matrices. Otherwise print one line containing the number of elementary multiplications needed to evaluate the expression in the way specified by the parentheses.

Sample Input

9
A 50 10
B 10 20
C 20 5
D 30 35
E 35 15
F 15 5
G 5 10
H 10 20
I 20 25
A
B
C
(AA)
(AB)
(AC)
(A(BC))
((AB)C)
(((((DE)F)G)H)I)
(D(E(F(G(HI)))))
((D(EF))((GH)I))

Sample Output

0
0
0
error
10000
error
3500
15000
40500
47500
15125

题目链接: UVA 12404 Excitement Levels SPOJ EXCITE - Excitement Levels Codeforces 583E - Watching Fireworks is Fun 题意概述: 有两只奶牛Bessie和Elsie通过一个电话线交换消息,每条消息可能是Bessie发出的、Elsie发出的,或两只奶牛都发出的。我们将Bessie和Elsie发出的消息的序列表示为两个字符串$B$和$E$,其中$B$表示Bessie发送的消息,$E$表示Elsie发送的消息。例如:当$B = \texttt{AEABBABA}$且$E = \texttt{BEABEAE}$时,下表描述了这两只奶牛之间的一些有可能的信息交换: $$ \begin{array}{|c|c|c|} \hline \textbf{位置} & \textbf{消息} & \textbf{发送方} \\ \hline 1 & A & B \\ \hline 2 & E & E \\ \hline 3 & A & E \\ \hline 4 & B & B \\ \hline 5 & A & E \\ \hline 6 & B & A \\ \hline 7 & A & B \\ \hline 8 & E & A \\ \hline 9 & - & - \\ \hline \end{array} $$ 对于给定的字符串$B$和$E$,我们可以尝试恢复出她们发送的所有消息。让$S$表示任意一种可能的恢复方案中,两只奶牛发送的所有消息组成的序列。例如:上表中的恢复方案为$\texttt{AEABBAEAB}$,其中有两个BB子串和两个EE子串。我们将$S$中BB子串和EE子串的总数称为这个方案的兴奋水平。 现在,给定$B$和$E$,请你计算出所有可能的兴奋水平,并把它们按从小到大的顺序输出。 题解: 一些定义: $B$的长度为$n$。 $E$的长度为$m$。 如果我们知道了一个恢复方案,那么我们可以在$O(n + m)$的时间内判断它的兴奋水平。具体来说,我们可以使用一个单调来计算所有在$S$中以BB或EE为结尾的子串的数量,其中中存储了在$S$中以B或E为结尾的子串的个数。 根据上面的定义,我们可以发现给定任意一个$S$,我们可以用单调在$O(n + m)$的时间内计算出$S$的兴奋水平,但是一个字符串有$n + m - 1$个位置,因此存在$(n + m - 1)!$多种可能的$S$。我们显然不能枚举所有的$S$。 解决方案: 我们可以直接计算出所有满足条件的$S$。具体来说,我们可以在一个递归的函数中,构建一个字符数组$S$,表示目前为止我们已经选择了哪些字符。在每个递归调用中,我们都会向$S$中添加一个字符——当前字符序列中次数较少的一个字符。如果$S$已经被填满,那么我们就可以在$O(n + m)$的时间内计算出当前方案的兴奋水平,并将其添加到答案数组中。这个递归函数的时间复杂度为$O((n + m)! (n + m))$,空间复杂度也为$O((n + m)!)$。在本题的数据范围内,这个算法可以通过本题。 代码:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值