2024年CSP-J暑假冲刺训练营(5):表达式求值

一、栈

1. 意义

栈,后进先出 的一种数据结构( L I F O \tt LIFO LIFO),是只能在某一端插入和删除的特殊线性表,进行删除和插入的一端称作栈顶,另一端称作栈底。

2. 数组模拟

(1) 初始化

const int n = 105;
int s[n];
int top = 0;

(2) 相关函数

void push(int x) {
    if (top < n) {
        s[++top] = x;
    } else {
        // 上溢处理...
    }
}

void pop() {
    if (top > 0) {
        top--;
    } else {
        // 下溢处理...
    }
}

int getTop() {
    return s[top];
}

bool isEmpty() {
    return (top == 0);
}

int sizeStack() {
    return top;
}

二、例题

1. 车厢调度

小明暑假来到火车站参与暑期实践,这里每辆火车从 A \tt A A 驶入,再从 B \tt B B 方向驶出,同时它的车厢可以重新组合。假设从 A \tt A A 方向驶来的火车有 n n n 节( n ≤ 1000 n\le1000 n1000),分别按照顺序编号为 1 ∼ n 1\sim n 1n。假定在进入车站前,每节车厢之间都不是连着的,并且它们可以自行移动到 B \tt B B 处的铁轨上。另外假定车站 C \tt C C 可以停放任意多节车厢。但是一旦进入车站 C \tt C C,它就不能再回到 A \tt A A 方向的铁轨上了,并且一旦当它进入 B \tt B B 方向的铁轨,它就不能再回到车站 C \tt C C。负责车厢调度的工作人员需要知道能否使它以 a 1 , a 2 , ⋯   , a n a_1,a_2,\cdots,a_n a1,a2,,an 的顺序从 B \tt B B 方向驶出,请判断能否得到指定的车厢顺序。

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

int n, x;
int num = 1;
stack <int> s;

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        while (num <= x) s.push(num++);
        if (s.top() != x) {
            cout << "NO";
            return 0;
        } else {
            s.pop();
        }
    }
    cout << "YES";
    return 0;
}

2. 括号匹配 3.0

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

string str;
int n, d[280];
stack<int> s;

int main() {
    freopen("bracket.in", "r", stdin);
    freopen("bracket.out", "w", stdout);

    d['<'] = 4, d['>'] = -4;
    d['('] = 3, d[')'] = -3;
    d['['] = 2, d[']'] = -2;
    d['{'] = 1, d['}'] = -1;

    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> str;
        bool flag = true;
        for (char c : str) {
            if (d[c] >= 0) {
                if (s.empty() || d[c] >= s.top()) s.push(d[c]);
                else {
                    flag = false;
                    break;
                }
            } else {
                if (s.empty() || s.top() + d[c] != 0) {
                    flag = false;
                    break;
                } else {
                    s.pop();
                }
            }
        }
        if (flag && s.size() == 0) cout << "YES\n";
        else cout << "NO\n";
        while (!s.empty()) s.pop();
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}

3. [USACO11FEB] Best Parenthesis S

Recently, the cows have been competing with strings of balanced parentheses and comparing them with each other to see who has the best one.
Such strings are scored as follows (all strings are balanced): the string '()' has score 1 1 1; if 'A' has score s ( A ) s(A) s(A) then '(A)' has score 2 × s ( A ) 2\times s(A) 2×s(A); and if 'A' and 'B' have scores s ( A ) s(A) s(A) and s ( B ) s(B) s(B), respectively, then 'AB' has score s ( A ) + s ( B ) s(A)+s(B) s(A)+s(B). For example, s('(())()') = = = s('(())')+s('()') = 2 × = 2\times =2× s('()') + 1 = 2 × 1 + 1 = 3 +1 = 2\times 1+1 = 3 +1=2×1+1=3.
Bessie wants to beat all of her fellow cows, so she needs to calculate the score of some strings. Given a string of balanced parentheses of length N N N( 2 ≤ N ≤ 100 , 000 2 \le N \le 100,000 2N100,000), help Bessie compute its score.

#include <iostream>
#include <stack>
#define int long long
using namespace std;

const int MOD = 12345678910;

int n, x, top;
int s[1001000];

signed main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        if (x == 0) s[++top] = 0;
        else {
            if (s[top] == 0) {
                s[top-1] = (s[top-1] + 1) % MOD;
                top--;
            } else {
                s[top-1] = (s[top-1] + s[top] * 2) % MOD;
                top--;
            }
        }
    }
    cout << s[0];
    return 0;
}

4. 前缀表达式求值

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

int x, k = 1, num;
int s[100], top;
char c;
string a;

int main() {
    cin >> a;
	for (int i = a.length()-2; i >= 0; i--) {
		c = a[i];
		if (c >= '0' && c <= '9') {
			num = (c-'0')*k+num;
			k *= 10;
		} else if (c == '.') {
			s[++top] = num;
			k = 1, num = 0;
		} else {
			x = s[top--];
			if (c == '+') s[top] = x + s[top];
			else if (c == '-') s[top] = x - s[top];
			else if (c == '*') s[top] = x * s[top];
			else if (c == '/') s[top] = x / s[top];
		}
	}
	cout << s[top];
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值