栈的专题1

目录

A. 表达式求值

说明

输入格式

输出格式

样例

输入数据 1

输出数据 1

B. 栈 

说明

输入格式

输出格式

样例

输入数据 1

输出数据 1

C. 「一本通 5.1 练习 1」括号配对 

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

D. 奶牛舞会 

Description

Format

Input

Output

Samples

输入数据 1

输出数据 1

Samples

输入数据 2

输出数据 2

Limitation


A. 表达式求值

说明

给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。

输入格式

每组输入数据仅有一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”和乘法运算符“*”,且没有括号,所有参与运算的数字均为0到231-1之间的整数。输入数据保证这一行只有0~9、+、*这12种字符。

数据规模:

对于30%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100;

对于80%的数据,0≤表达式中加法运算符和乘法运算符的总数≤1000;

对于100%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100000。

输出格式

每组输出只有一行,包含一个整数,表示这个表达式的值。注意:当答案长度多于4位时,请只输出最后4位,前导0不输出。

下面是对样例数据的解释:

样例1计算的结果为8,直接输出8。

样例2计算的结果为1234567891,输出后4位,即7891。

样例3计算的结果为1000000004,输出后4位,即4。

样例

输入数据 1


1+1*3+4
1+1234567890*1
1+1000000003*1

Copy

输出数据 1


8
7891
4

由于是一个只包含加法和乘法的算术表达式,所以我们可以先将乘法全部处理之后再处理加法

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int mod = 10000;
int f;
int ls;
int sum;
int main() {
    string s;
    while (cin >> s) {
        stack<char>st;//保存‘+’号
        stack<int>st2;//保存数字
        int q = 0;
        int ppx = s.size();
        for (int i = 0; i < ppx; i++) {
            if (s[i] >= '0' && s[i] <= '9') {//算出数字的结果
                q = (q * 10 + (s[i] - '0')) % mod;
            }
            if (i == ppx - 1||s[i]=='+'||s[i]=='*') {//如果不是数字
                if (f) {//如果这个数字前面是‘*’号,算出乘后的结果入栈
                    q = q * ls % mod;
                    st2.push(q);
                    f = 0;
                }
                else st2.push(q);//直接进栈
                q = 0;
                if (s[i] == '+') {//如果是‘+’号,直接入栈
                    st.push(s[i]);
                }
                else if (s[i] == '*') {//如果是‘*’号,用ls记录‘*’号前的数字
                    ls = st2.top();
                    st2.pop();
                    f = 1;
                }
            }
        }
        while (st.size()) {//对‘+’法进行处理
            st.pop();
            int l = st2.top();
            st2.pop();
            int r = st2.top();
            st2.pop();
            st2.push((l + r) % mod);
        }
        cout << st2.top() << endl;//输出结果
    }
    return 0;
}

B. 栈 

说明

栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。

栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈)。

栈的重要性不言自明,任何一门数据结构的课程都会介绍栈。宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙。

宁宁考虑的是这样一个问题:一个操作数序列,从1,2,一直到n(图示为1到3的情况),栈A的深度大于n。

现在可以进行两种操作:

1. 将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的push操作)
2. 将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的pop操作)

使用这两种操作,由一个操作数序列就可以得到一系列的输出序列,下图所示为由1 2 3生成序列2 3 1的过程。(原始状态如上图所示)

你的程序将对给定的n,计算并输出由操作数序列1,2,...,n经过操作可能得到的输出序列的总数。

输入格式

输入只含一个整数n(1≤n≤18)。

输出格式

输出只有一行,即可能输出序列的总数目。

样例

输入数据 1

3

Copy

输出数据 1

5

遇事不绝就百度,可知此题的结果是卡特兰数的规律:

设h(n)为catalan数的第n项,令h(0)=1,h(1)=1,catalan数满足递推式:h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0) (n≥2)

所以直接写代码即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
int ca[20];
//设h(n)为catalan数的第n项,令h(0)=1,h(1)=1,catalan数满足递推式
//h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0) (n≥2)
ll Catalan(int n) {
    if (ca[n]) {
        return ca[n];
    }
    if (n == 0||n==1) {
        ca[n] = 1;
        return 1;
    }
    for (int i = 0; i <= n - 1; i++) {
        ca[n] += Catalan(i) * Catalan(n - i - 1);
    }
    return ca[n];
}
int main() {
    cin >> n;
    cout << Catalan(n);//卡特兰数
    return 0;
}

C. 「一本通 5.1 练习 1」括号配对 

题目描述

Hecy 又接了个新任务:BE 处理。BE 中有一类被称为 GBE。

以下是 GBE 的定义:

  1. 空表达式是 GBE
  2. 如果表达式 A 是 GBE,则 [A] 与 (A) 都是 GBE
  3. 如果 A 与 B 都是 GBE,那么 AB 是 GBE

下面给出一个 BE,求至少添加多少字符能使这个 BE 成为 GBE。

输入格式

输入仅一行,为字符串 BE。

输出格式

输出仅一个整数,表示增加的最少字符数。

样例

输入数据 1

[])

Copy

输出数据 1

1

Copy

数据范围与提示

对于 100%100% 的数据,输入的字符串长度小于 100100。

区间dp,从1~n逐步推出最佳结果,重点是理清思路趴,大家多看几遍

#include <bits/stdc++.h>
using namespace std;
int f[105][105];//f[i][j]是区间i到j的最少操作数
int main() {
    string s;
    cin >> s;
    int n = s.size();
    for (int i = 0; i < n; i++)f[i][i] = 1;
    //当区间长度为0时,每个字符找到匹配的操作数为1
    for (int L = 1; L < n; L++) { //枚举区间长度
        for (int i = 0; i + L < n; i++) { //遍历区间起点
            int j = i + L;//区间终点
            f[i][j] = 1e9;//首先赋一个最大的值
            for (int k = i; k < j; k++) //遍历区间
                f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j]);
            if ((s[i] == '[' && s[j] == ']') || (s[i] == '(' && s[j] == ')'))  //如果括号匹配
                f[i][j] = min(f[i][j], f[i + 1][j - 1]);
        }
    }
    /*for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << f[i][j] << ' ';
        }
        cout << endl;
    }*/
    cout << f[0][n - 1] << endl;
    return 0;
}

D. 奶牛舞会 

Description

每年春天,奶牛们会举行一个盛大的舞会。

舞会上公牛(表示为">")和母牛(表示为"<")相互鞠躬以后开始舞蹈。

原则上,一对相互鞠躬的牛表示为:"><"。直接这样"<>"都不行;

有时候,另一对牛会处在一对相互鞠躬的牛中间:"> >< <"。

事实上,有些时候舞厅会有非常多的牛会混杂在一起:"> >< < ><"。

会比上面的例子更复杂一点(右侧又多加了一对相互鞠躬的牛)。

如下是一个更复杂但合法的安排: > > > >< < >< < >< >< >< <

Farmer John注意到有时会有游荡的牛闯入一组跳舞者中,因此这个跳舞组变得不平衡:"> >< < <><"。 这是严格禁止的。

Farmer John想要惩罚这些闯入者。 Farmer John整理出一些跳舞队列的记录。每个跳舞队列最多有500只牛。

他想要知道这些跳舞队列是否平衡。

平衡也就是说至少有一种方案可以使每头牛都加入一个鞠躬对。

Format

Input

Farmer John一共整理出​ ==N组记录(1 <= N <= 1,000)==​。

第i组记录由字符('>' and '<')和一个表示长度的K_i (1 <= K_i <=200)构成。 .

Output

如果记录可以平衡,输出"legal",否则,输出"illegal".

Samples

输入数据1

输入数据 1

2
6 >><<><
4 ><<>

Copy

输出数据 1

legal
illegal

Copy

输出数据1

Samples

输入数据2

输入数据 2

7
5 <<<<<
5 >>>>>
2 ><
3 >><
9 >><<><><<
11 ><><>><<>><
4 >><<

Copy

输出数据 2

illegal
illegal
legal
illegal
illegal
illegal
legal

Copy

输出数据2

Limitation

1s, 1024KiB for each test case.

签到题趴,放在最后的最简单

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        stack<char>st;
        for (int i = 0; i < n; i++) {
            char x;
            cin >> x;
            if (x == '>') {
                st.push(x);
            }
            else {
                if (st.size()&&st.top() == '>') {//如果栈不为空且栈顶元素和现有元素匹配
                    st.pop();
                }
                else st.push(x);
            }
        }
        if (st.size())cout << "illegal\n";
        else cout << "legal\n";
    }
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值