【题目链接】

ybt 2006:【20CSPJ普及组】表达式
洛谷 P7073 [CSP-J2020] 表达式

【题目考点】

  1. 后缀表达式
  2. 表达式树

通过后缀表达式建立表达式树:

  • 遍历后缀表达式字符串:

    • 若读取到数字,生成结点,入栈
    • 若读取到运算符,生成运算符结点,出栈两个结点,分别作为运算符结点的左右孩子,将运算符结点入栈
  • 最后栈顶结点就是表达式树的根结点

【解题思路】

  • 题中求的是布尔表达式,问改变某个变量的值后,整个式子的值是否变化。
    由此可知,我们需要求出一个布尔型的数组isChange

    • isChange[i]为真,表示第i个变量变化后,表达式的值会变化。
    • isChange[i]为假时,表示第i个变量变化后,表达式的值不会变化。
  • 考察表达式a|b,当a为0,b为1时,0|1结果为0。此时如果a发生改变,式子变为1|1,结果为1。如果b发生改变,式子变为0|0结果为0。说明a的改变可以改变表达式的值,而b的改变不会改变表达式的值。
    由于运算数只有0、1,运算符只有&、|,可以枚举不同的表达式中改变两个变量后能否改变表达式的值,将这些情况保存起来,设为两个数组isChAnd和isChOr。

    • isChAnd[a][b][c]: 在a&b这一表达式中,a(c为0)或b(c为1)的值变化能否影响运算的结果。
    • isChOr[a][b][c]: 在a|b这一表达式中,a(c为0)或b(c为1)的值变化能否影响运算的结果。
  • 通过后缀表达式建立表达式树
    • 叶子结点记录变量编号(x),变量值(val)
    • 每个子树都是一个表达式。分支结点记录以该结点为根的子树所表示的表达式的值(val)、该结点的值如果变化对父结点的值是否有影响(inf)。
  • 判断哪些变量变化会对整体表达式的值有影响,构造isChange数组
    • 如果一个结点的变化对其父结点没有影响,那么该结点所有孩子结点的变化对父结点都没有影响。即以该结点为根结点的子树的叶子结点对应的变量的变化对整体表达式的值没有影响。
    • 遍历表达式树,如果遇到自身值变化不会影响父结点的结点,那么,就不再向下遍历。以此方法,遍历到的所有叶子结点对应的变量,其变化都会影响整体表达式的值,对应地设置isChange数组。
  • 根据题目需要,查询isChange数组,输出结果。

【题解代码】

解法1:

#include <bits/stdc++.h>
using namespace std;
#define N 1000005
typedef struct Node//表达式树结点
{int left, right;bool val;//值bool inf;//本节点值的改变是否能影响父结点int x;//该结点的变量编号
}Node;
bool val[N];//val[i]:变量x[i]的初值
char s[N];//读入的字符串
Node node[N];//结点池
int ni = 1;//结点池下标
bool isChange[N];//isChange[i] 第i个变量变化后,能否影响最终结果
//isChAnd[a][b][c]: 当第1个数的值是a,第2个数值是b时,第c+1个数的值变化能否影响运算的结果。
//例:0&0 = 0 第一个数0变为1,公式变为1&0 = 0,不能影响运算结果。那么有isChAnd[0][0][0] = false;
bool isChAnd[2][2][2], isChOr[2][2][2];
//初始化isChAnd和isChOr
void initIsCh()
{isChAnd[0][0][0] = 0;  isChAnd[0][0][1] = 0;isChAnd[0][1][0] = 1;  isChAnd[0][1][1] = 0;isChAnd[1][0][0] = 0;  isChAnd[1][0][1] = 1;isChAnd[1][1][0] = 1;  isChAnd[1][1][1] = 1;isChOr[0][0][0] = 1;  isChOr[0][0][1] = 1;isChOr[0][1][0] = 0;  isChOr[0][1][1] = 1;isChOr[1][0][0] = 1;  isChOr[1][0][1] = 0;isChOr[1][1][0] = 0;  isChOr[1][1][1] = 0;
}
//生成表达式树,返回根节点的地址
int initTree()
{stack<int> stk;//存放结点地址int xNum = 0, np, lp, rp;//xNum:变量编号 np:新结点地址 lp,rp:左右孩子地址 char cal;//运算符int len = strlen(s);for(int i = 0; i <= len; ++i){if(s[i] >= '0' && s[i] <= '9')xNum = xNum * 10 + s[i] - '0';else if(s[i] == '&' || s[i] == '|' || s[i] == '!')cal = s[i];else if(s[i] == ' ' || s[i] == '\0'){if(xNum > 0)//提取出x{np = ni++; node[np].val = val[xNum];node[np].x = xNum;stk.push(np);xNum = 0;}else//提取出运算符{np = ni++;if(cal == '!'){lp = stk.top();stk.pop();node[lp].inf = true;//取非运算的运算数的改变会影响表达式的值node[np].val = !node[lp].val;node[np].left = lp;}else{rp = stk.top();stk.pop();lp = stk.top();stk.pop();node[np].left = lp;node[np].right = rp;if(cal == '&'){node[np].val = node[lp].val && node[rp].val;node[lp].inf = isChAnd[node[lp].val][node[rp].val][0];node[rp].inf = isChAnd[node[lp].val][node[rp].val][1];}else if(cal == '|'){node[np].val = node[lp].val || node[rp].val;node[lp].inf = isChOr[node[lp].val][node[rp].val][0];node[rp].inf = isChOr[node[lp].val][node[rp].val][1];}}stk.push(np);}}}return stk.top();
}
//设置isChange数组 遍历表达式树
void initIsChange(int p)
{if(node[p].inf)//如果该点值的变化不能影响父结点 ,就不遍历了。{if(node[p].left == 0 && node[p].right == 0){isChange[node[p].x] = true;//如果遍历到叶子结点,那么设置该变量的变化可以影响表达式的值}else{if(node[p].left != 0)initIsChange(node[p].left);if(node[p].right != 0)initIsChange(node[p].right);}}
}int main()
{initIsCh();int n, q, qi;bool res;//正常计算的结果cin.getline(s, N);scanf("%d", &n);for(int i = 1; i <= n; ++i)//输入各个变量的值scanf("%d", &val[i]);int root = initTree();//生成表达式树res = node[root].val;//通过已有变量值求出的表达式的原始结果node[root].inf = true;//为了配合下面的函数,必须设这一点initIsChange(root);//设置isChange数组scanf("%d", &q);//输入查询组数for(int i = 1; i <= q; ++i){scanf("%d", &qi);//改变第qi变量if(isChange[qi])//如果第qi变量的改变能引起表达式值的变化printf("%d\n", !res);//输出变化后的结果elseprintf("%d\n", res);//输出原结果}return 0;
}

信息学奥赛一本通 2006:【20CSPJ普及组】表达式 | 洛谷 P7073 [CSP-J2020] 表达式相关推荐

  1. Java P1035 [NOIP2002 普及组] 级数求和 洛谷入门题

    P1035 [NOIP2002 普及组] 级数求和 题目描述 已知:Sn=1+1/2+1/3+-+1/nS_n= 1+1/2+1/3+-+1/nSn​=1+1/2+1/3+-+1/n.显然对于任意一个 ...

  2. 每日一题 --- P1093 [NOIP2007 普及组] 奖学金[洛谷][JAVA]

    题目: 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金.期末,每个学生都有3门课的成绩:语文.数学.英语.先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到 ...

  3. 信息学奥赛一本通 提高篇 第六部分 数学基础 相关的真题

    第1章   快速幂 1875:[13NOIP提高组]转圈游戏 信息学奥赛一本通(C++版)在线评测系统 第2 章  素数 第 3 章  约数 第 4 章  同余问题 第 5 章  矩阵乘法 第 6 章 ...

  4. 信息学奥赛一本通 2004:【20CSPJ普及组】优秀的拆分 | 洛谷 P7071 [CSP-J2020] 优秀的拆分

    [题目链接] ybt 2004:[20CSPJ普及组]优秀的拆分 洛谷 P7071 [CSP-J2020] 优秀的拆分 [题目考点] 数制 基数:即进制数.十进制的基数是10,二进制的基数是2. 按位 ...

  5. 信息学奥赛一本通 2005:【20CSPJ普及组】直播获奖 | 洛谷 P7072 [CSP-J2020] 直播获奖

    [题目链接] ybt 2005:[20CSPJ普及组]直播获奖 洛谷 P7072 [CSP-J2020] 直播获奖 [题目考点] 计数排序(桶排序) 其核心为:设计数数组c,c[i]表示数字i出现的个 ...

  6. 信息学奥赛一本通 2007:【20CSPJ普及组】方格取数 | 洛谷 P7074

    [题目链接] ybt 2007:[20CSPJ普及组]方格取数 洛谷 P7074 [CSP-J2020] 方格取数 [题目考点] 1. 坐标型动规 [解题思路] 确定状态:a[i][j]为从起点走到i ...

  7. 信息学奥赛一本通 1358:中缀表达式值(expr)

    [题目链接] ybt 1358:中缀表达式值(expr) [题目考点] 1. 表达式求值 中缀表达式转后缀表达式 后缀表达式求值 [解题思路] 由于题目要求做中缀表达式转为后缀表达式,而后求值.那么这 ...

  8. 信息学奥赛一本通(C++版)NOIP提高组(1820-1829)

    信息学奥赛一本通(C++版)NOIP提高组目录 //1820 [题目描述] 我们可以用这样的方式来表示一个十进制数:将每个阿拉伯数字乘以一个以该数字所 处位置的(值减1)为指数,以10为底数的幂之和的 ...

  9. 信息学奥赛一本通在线提交地址

    信息学奥赛一本通 1 C++语言入门 1.1 综合 1.1.1 P1458 地球人口承载力估计 正确: 770 提交: 1794 比率: 42.92 % 1.1.2 P1686 Hello, Worl ...

最新文章

  1. sap 彻底删除物料主档
  2. 学python最重要的是_基础、语法都不是最重要的,学Python最重要的是什么?编程思路!-站长资讯中心...
  3. k8s minikube在wsl中通过nodeport来访问
  4. 37个JavaScript基本面试问题和解答
  5. UE4 VR中一种比较清晰的UI制作方式
  6. 在Python中给定包含该项目的列表的情况下查找项目的索引
  7. Android 中的线程有哪些,原理与各自特点
  8. 管理感悟:公司内斗,肯定是闲着的斗干活的
  9. 记一次自动提醒钉钉机器人的诞生
  10. android输入法ios下载安装,仿ios输入法
  11. 数分下第12讲(第9.6节) 梯度散度和旋度
  12. Java常用英语汇总(面试必备)
  13. usb keyboard找不到驱动程序_台式机也能用上蓝牙,毕亚兹USB蓝牙适配器体验
  14. RFB-Net论文代码映射
  15. matlab百分号是什么意思,matlab 两个百分号
  16. 学计算机独显重要吗,“集显”、“独显”对于普通电脑用户来说还那么重要吗?...
  17. 看日漫学日语:日漫里常看到的日语100句(建议收藏)
  18. 深度学习图像处理目标检测图像分割计算机视觉 04--神经网络与误差反向传播BP算法
  19. shell中test命令用法详解
  20. Java小项目——客户的关系管理系统

热门文章

  1. OpenSSH 远程拒绝服务漏洞
  2. VMWare的The network bridge on device VMnet0 is not running故障解决
  3. 获取指定路径下的所有文件
  4. 最新,Python终成第1!Java和C长期霸榜时代结束
  5. range作用于对象global失败_彻底弄懂JavaScript作用域问题
  6. 说说我在制造业大厂当了一个月程序员的感受
  7. IDEA发布新版本,支持禅模式(免打扰)!
  8. 原创 | 万万没想到,JVM内存结构的面试题可以问的这么难?
  9. 万亿级流量高可用延时服务架构设计
  10. 我要重构“软件行业”......