10 条题解
-
0
题目分析:
我们需要让计算机计算这一条逻辑表达式的值,并计算短路的个数。
首先,短路分为两种:
-
与短路:0&---------的结果一定是0;
-
或短路:1|---------的结果一定是1;
以
0&(1|0)|(1|1|1&0)
为例, 短路情况:0& 1| 1|
其次,我们需要将中缀表达式改写成后缀表达式:
用一个vector记录后缀表达式sf,用一个stack记录操作符ops;
具体扫描规则如下:
- 优先级别:第一级是(),第二级是&,第三级是|。
- 遇到数字时,将数字push进sf;
- 遇到(时,将( push进ops;
- 遇到)时,将上一个(前的运算符全部转移到sf中,ops pop掉(。
- 遇到运算符时,将运算符转移到sf,直到ops为空或者计算级别不同,再将此运算符push进去。
最后将剩下的ops全部移到sf中。
如扫描
1|(1|1)&(0&1)
:- 扫到1,ops不变,sf为1;
- 扫到|,ops为|,sf不变;
- 扫到(,ops为|(,sf不变;
- 扫到1,ops不变,sf为11;
- 扫到|,ops为|(|,sf为不变;
- 扫到1,ops不变,sf为111;
- 扫到),ops为|,sf为111|;
- 扫到&,ops为|&,sf不变;
- 扫到(,ops为|&(,sf不变;
- 扫到0,ops不变,sf为111|0;
- 扫到&,ops为|&(&,sf不变;
- 扫到1,ops不变,sf为111|01;
- 扫到),ops为|&,sf为111|01&;
- 最后,sf为
111|01&&|
然后,我们需要将中缀表达式转换成表达式树:
我们需要声明一个结构体数组
tr
用于存放树的每个节点的值v
,左子树位置和右子树位置l和r
,声明一个栈sta
来缓存每个节点的位置所有叶子节点的值都为其对应的数字,用于计算。所有非叶子节点的值都为其对应运算符的值,也就是按照运算优先级的顺序:
&
=2,|
=3,所有叶子节点的左子树和右子树位置都为-1
,因为叶子结点根本就没有左子树和右子树.最后,我们通过dfs (深搜)来访问表达式树并计算。
具体访问规则如下:
- 若访问节点的`l`和`r`都是`-1`,直接返回`v`,否则进入第二点;
- 计算左节点的数值;
- 判断是否出现短路情况,如出现直接返回对应数值;
- 计算并返回右节点的数值。
代码:
#include<iostream> #include<vector> #include<stack> using namespace std; string s; const int N=1e6+5; struct Node{ int v,l,r; }tr[N]; int num,ans1,ans2; stack<char>ops; stack<int>sta; vector<char>sf; void change()*//* *中缀表达式转后缀表达式* { for(int i=0;i<s.size();i++) { if(s[i]=='0'||s[i]=='1') sf.push\_back(s[i]); *//**扫到数字,直接插入**sf* else if(s[i]=='(') ops.push(s[i]); *//* *扫到左边括号,插入运算符栈* else if(s[i]==')') { while(!ops.empty()&&ops.top()!='(') { sf.push\_back(ops.top());*//* *一直输出到**sf**。直到遇上**( * ops.pop(); } ops.pop(); *//* *输出多余的(* } else if(s[i]=='&') { *//**与运算* while(!ops.empty()&&ops.top()=='&') { sf.push\_back(ops.top()); ops.pop(); } ops.push('&'); } else { *//**或运算* while(!ops.empty()&&ops.top()!='(') { sf.push\_back(ops.top()); ops.pop(); } ops.push('|'); } } while (!ops.empty()) { sf.push\_back(ops.top()); ops.pop(); } } void build() { for(int i=0;i<sf.size();i++) { if(sf[i]=='1'||sf[i]=='0') { tr[++num]={sf[i]-'0',-1,-1}; sta.push(num); } else { int r=sta.top(); sta.pop(); int l=sta.top(); sta.pop(); int v=(sf[i]=='&'?2:3); tr[++num]={v,l,r}; sta.push(num); } } } int dfs(int u) { if(tr[u].v==0||tr[u].v==1) return tr[u].v; *//**叶子节点* *。返回数值* int l=dfs(tr[u].l); if(l==0&&tr[u].v==2) {*//0&* ans1++; return 0; } if(l==1&&tr[u].v==3) {*//1|* ans2++; return 1; } int r=dfs(tr[u].r); return r; } int main() { cin>>s; change(); build(); cout<<dfs(num)<<endl; cout<<ans1<<" "<<ans2; return 0; }
-
信息
- ID
- 2918
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 156
- 已通过
- 48
- 上传者