CSP历年复赛题-P8815 [CSP-J 2022] 逻辑表达式
原题链接:https://www.luogu.com.cn/problem/P8815
题意解读:计算逻辑表达式的值以及&,|短路操作的次数。
解题思路:
又是一道经典的中缀表达式的变形问题,
如果对中缀表示式如何求值不理解,移步https://www.acwing.com/problem/content/3305/进行复习
如果对表示式如何构建树形结构以及通过树形结构来求值不理解,可以移步https://www.cnblogs.com/jcwy/p/18247992进行复习
对于本题:思路是通过双栈来将中缀表达式构建成树形结构,然后dfs来求值
对于一个节点u:
如果是&操作,
如果左子节点是0,则&短路次数+1,只需继续dfs左子树,不需要计算右子树
否则继续dfs左、右子树
如果是|操作,
如果左子节点是1,则|短路次数+1,只需要继续dfs左子树,不需要计算右子树
否则继续dfs左、右子树
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
string expr;
stack<int> op; //运算符栈,存的都是树的节点编号
stack<int> num; //操作数栈,存的都是树的节点编号
int l[N], r[N], w[N], idx; //二叉树每个节点的的左子树、右子树、值,idx是节点编号
char o[N]; //二叉树每个符号节点的内容: &,|
int ans1, ans2;
map<char, int> priority = {{'|', 1}, {'&', 2}}; //定义|和&的优先级
void eval()
{
int a = num.top(); num.pop();
int b = num.top(); num.pop();
int x = op.top(); op.pop();
int res;
if(o[x] == '&') res = w[a] & w[b];
if(o[x] == '|') res = w[a] | w[b];
//构建树,先入栈的b为x左子节点,后入栈的a为x右子节点
l[x] = b, r[x] = a;
//更新x节点的值
w[x] = res;
//计算之后的结果节点编号入num栈
num.push(x);
}
void dfs(int root)
{
if(o[root] == '&')
{
if(w[l[root]] == 0) ans1++, dfs(l[root]); //左子结点是0,a&b短路次数+1
else dfs(l[root]), dfs(r[root]);
}
else if(o[root] == '|')
{
if(w[l[root]] == 1) ans2++, dfs(l[root]); //左子结点是1,a|b短路次数+1
else dfs(l[root]), dfs(r[root]);
}
}
int main()
{
cin >> expr;
for(int i = 0; i < expr.size(); i++)
{
if(expr[i] == '0' || expr[i] == '1')
{
w[++idx] = expr[i] - '0'; //生成操作数在树中节点编号,节点值保存
num.push(idx); //数字节点入num栈
}
else if(expr[i] == '(')
{
o[++idx] = expr[i]; //生成节点编号,节点值保存
op.push(idx); //左括号节点直接入op栈
}
else if(expr[i] == ')') //右括号,要从栈中取出操作数和运算符构建树
{
while(o[op.top()] != '(') eval();
op.pop(); //弹出'('
}
else if(expr[i] == '&' || expr[i] == '|')
{
while(op.size() && priority[expr[i]] <= priority[o[op.top()]]) //如果当前符号优先级<=当前栈顶符号优先级
eval();
o[++idx] = expr[i]; //生成运算符在树中节点编号,节点值保存
op.push(idx); //将符号节点入op栈
}
}
while(op.size()) eval();
cout << w[num.top()] << endl;
dfs(num.top());
cout << ans1 << " " << ans2;
return 0;
}
分类:
CSP-J复赛真题解析
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?