L2-053 算式拆解
祛魅题

解题思路
与acwing的表达式求值同出一辙 , 这是acwing题目传送门,再来看这一题,其实几乎可以套模板了(还是有点跨度的),由于题目只是要求输出计算步骤,而不是每一步的结果,所以用字符串更方便,而且我们这里的数栈用的是string类型,避免我们的标记值与题目数据冲突。
重点 : 本题最重要的题目条件就是:算式的通用格式为 (对象 操作 对象),也就是每个右括号都代表着一个层级,每遇到一个右括号就要立马进入最近的操作 ,然后执行对 A op B的处理,变成标记符后放回num里(必须放回o(>﹏<)o ),重复该操作。
大家可以自己试一下,其实这个逻辑和代码的实现都是很简单的,但是对于从未接触过表达式求值这类题目的同学来说,这是一道hard题。
不过仍然需要注意很多细节问题,比如运算符是字符型,所以op的stack也是op型的,
ac✅️代码
#include <iostream>
#include <string>
#include <stack>
#include <vector>
using namespace std;
// 使用 string 栈避开数值溢出和标记冲突
stack<string> num_stack;
stack<char> op_stack;
// 存储程序中间值的变量名标记
const string xpmclzjkln = "RESULT_MARKER";
void eval()
{
// 右操作数先出栈
string b = num_stack.top(); num_stack.pop();
// 左操作数后出栈
string a = num_stack.top(); num_stack.pop();
// 运算符出栈
char c = op_stack.top(); op_stack.pop();
//看看哪个操作数已经被标记过了。
bool a_is_res = (a == xpmclzjkln);
bool b_is_res = (b == xpmclzjkln);
//标记过的不用再输出
if (a_is_res && b_is_res)
{
cout << c << endl;
}
else if (a_is_res)
{
cout << c << b << endl;
}
else if (b_is_res)
{
cout << a << c << endl;
}
else
{
cout << a << c << b << endl;
}
//到这里,对象 操作 对象 就变成了我们的标记
num_stack.push(xpmclzjkln);
}
int main()
{
// 提升 IO 速度
ios::sync_with_stdio(false);
cin.tie(0);
string s;
if (!(cin >> s)) return 0;
int n = s.size();
for (int i = 0; i < n; i++)
{
if (isdigit(s[i]))
{
string t = "";
while (i < n && isdigit(s[i]))
{
t += s[i++];
}
i--; // 补偿循环位移
num_stack.push(t);
}
else if (s[i] == '(')
{
// 题目保证 (A op B),左括号仅作占位,无需入栈
continue;
}
else if (s[i] == ')')
{
// 遇到右括号,立即处理该括号对内的唯一运算
eval();
}
else
{
// 存储运算符
op_stack.push(s[i]);
}
}
return 0;
}

浙公网安备 33010602011771号