POJ 2106-Boolean Expressions,双栈运用类似表达式求值!
首先声明此题后台可能极水(毕竟这种数据不好造!)。昨天写了一天却总是找不到bug,讨论区各种数据都过了,甚至怀疑输入有问题,但看到gets也可以过,难道是思路错了?
题意:V表示ture,F表示false,然后有三种位运算符‘!’、‘&’、'|'。其中'!'的优先级最高,‘|’的优先级最低。即优先级关系:! > & > | 。给你一串包含这些运算符的表达式当然了还有括号,要你判断最终结果是VorF。
先说说我的思路吧:符号栈和数值栈肯定是前提(数组模拟也无所谓)。由于‘!’和‘&’的运算等级较高,于是我们可以先把所有的‘!’和‘&’先进行运算,最后运算或(扫一遍无先后)。当然了,括号的优先级最最高,我们特判括号的情况。你可能要问‘!’和’&‘的优先级有大小,怎么判断先后呢,我们发现’!‘一般是在一个数值前面,当存入一个数值的时候可以直接运算,’&‘在两个数值之间,也是直接取数值栈顶的两个元素直接运算再入栈。就是因为’!‘只能在一个数值前或者括号前(括号内最终也会化为一个数值),所以如果’!‘和’&‘都出现了肯定会将’!‘先运算完再’&‘运算,本来也符合题意优先级之分。但为什么会wa这么多遍呢,next....
现在来说说括号怎么判,我们如果是出现'('的话直接先入符号栈,然后数值和符号也是直接入相应的栈再判断运算。但当’)‘出现意味着肯定有一个最近的’(‘与其配对,我们这时就要把括号里的先运算完对吧,但上述提到’!‘和’&‘都是一出现就直接运算了,所以这时的括号内只能是单个数值或很多’|‘,还是直接运算,到’(‘就截止了嘛。最后弹出’(‘。好像看起来没毛病,又是WA。原因为何?next.....
最后看其他人提交的代码结果发现他们根本没有判优先级,三种符号出现都是从左往右扫,这样也过?’!‘的情况肯定没问题,但’&‘和’|‘总得有个先后,一学弟给出一幅图画出单个’&‘和单个’|‘的所有情况让我猜想这样依次运算是否和先后运算的结果一样?草草的证明了一下貌似真的可以(急功近利),然后仿照这大家的思路做了做终于发现自己的问题出在哪了,原来在进行’!‘和’&‘运算的时候没有判断到’(‘应截止。还有在’(‘应当出栈的时候没有判断栈顶元素是否为’(‘。也是神奇,我的正确思路居然被这种样例hackde。这时仍接受着依次运算和先后运算的结果一样的观点,回到宿舍学姐再讨论群里提出这样一组数据:1|0&0
即 V|F&F。这样明显打破上述观点,然后用两种代码都试了试果然依次运算的结果是F,正解应该是V。不得不说自己没有仔细证明为了A题草草下定结论,不过所幸自己的代码是没有问题的。可能大家读题题意没有明确,却阴差阳错,集训队的读题能力貌似一直处于迷离状态。。。。
重(ji)点(tang):研究性学习真的是让人很兴奋,充分锻炼一个人的耐心与思维,在结论成果得出的那一刻仿佛即将升天般的快感,这种学习方式也值得我们利用,当前学习状态不禁让我想起了快餐文化这一概念,急功近利总不得有好的结果,沉心静气淡泊名利才能走的更远。不惜花了这么大的篇幅来引出这段话,就算个人体验了,不喜勿喷。
回到原题,下面给出三种代码:
思路1:WA。未正确判断好括号关系。
const int N=1e6+10;
stack<char>q1;
stack<int>q2;
char s[150];
void ch(char c)
{
if(c=='!')
{
int x1=q2.top();q2.pop();
x1=!x1;
q2.push(x1);
}
else if(c=='&')
{
int x1=q2.top();q2.pop();
int x2=q2.top();q2.pop();
q2.push(x1&x2);
}
else if(c=='|')
{
int x1=q2.top(); q2.pop();
int x2=q2.top(); q2.pop();
q2.push(x1|x2);
}
q1.pop();
}
int main()
{
int t=1;
char c;
while(1)
{
c=getchar();
if(c==' ') continue;
if(c=='\n'||c==EOF)
{
while(!q1.empty())
{
if(q1.top()!='(') ch(q1.top());
else q1.pop();
}
printf("Expression %d: ",t++);
if(q2.top()==1) puts("V");
else puts("F");
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
if(c==EOF) break;
else continue;
}
if(c==')')
{
while(!q1.empty()&&q1.top()!='(') ch(q1.top());
q1.pop();//本意是删去‘(’,但应该判断是否为空且栈顶是否为‘(’
}
else
{
if(c!='V'&&c!='F') q1.push(c);
else
{
if(c=='V') q2.push(1);
else q2.push(0);
while(!q1.empty())//应该判断‘(’截止
{
if(q1.top()!='!'&&q1.top()!='&') break;//‘!’和'&'优先
ch(q1.top());
}
}
}
}
return 0;
}
代码二:AC。
const int N=1e6+10;
stack<char>q1;
stack<int>q2;
char s[N];
void ch(char c)
{
if(c=='!')
{
int x=q2.top();
q2.pop();
q2.push(!x);
}
else if(c=='&')
{
int x1=q2.top();
q2.pop();
int x2=q2.top();
q2.pop();
q2.push(x1&x2);
}
else if(c=='|')
{
int x1=q2.top();
q2.pop();
int x2=q2.top();
q2.pop();
q2.push(x1|x2);
}
q1.pop();
}
int main()
{
int t=1;
while(gets(s))
{
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
int len=strlen(s);
for(int i=0; i<len; i++)
{
if(s[i]==' ') continue;
if(s[i]==')')
{
while(!q1.empty()&&q1.top()!='(') ch(q1.top());
if(!q1.empty()&&q1.top()=='(') q1.pop();//删去左括号
}
else
{
if(s[i]!='F'&&s[i]!='V') q1.push(s[i]);
else
{
if(s[i]=='F') q2.push(0);
else q2.push(1);
while(!q1.empty()&&q1.top()!='(')
{
if(q1.top()!='&'&&q1.top()!='!') break;
ch(q1.top());
}
if(!q1.empty()&&q1.top()=='(') q1.pop();
}
}
}
printf("Expression %d: ",t++);
while(!q1.empty()) ch(q1.top());
if(q2.top()==1) puts("V");
else puts("F");
}
return 0;
}
代码三:hacked V|F&F
const int N=1e3+10;
stack<char>q1;
stack<int>q2;
char s[N];
void deal(char tmp)
{
if(tmp==')') q1.pop();
else
{
if(tmp=='V') q2.push(1);
else q2.push(0);
}
while(!q1.empty()&&q1.top()!='(')
{
char c=q1.top();
q1.pop();
if(c=='!'&&!q2.empty())
{
int x=q2.top();
q2.pop();
q2.push(!x);
}
else if(c=='&'&&q2.size()>1)
{
int x1=q2.top();
q2.pop();
int x2=q2.top();
q2.pop();
q2.push(x1&x2);
}
else if(c=='|'&&q2.size()>1)
{
int x1=q2.top();
q2.pop();
int x2=q2.top();
q2.pop();
q2.push(x1|x2);
}
}
}
int main()
{
int t=1;
while(gets(s))
{
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
int len=strlen(s);
for(int i=0; i<len; i++)
{
if(s[i]==' ') continue;
if(s[i]=='F'||s[i]=='V'||s[i]==')') deal(s[i]);
else q1.push(s[i]);
}
printf("Expression %d: ",t++);
if(!q1.empty()) deal(q1.top());
if(q2.top()==1) puts("V");
else puts("F");
}
return 0;
}
POJ 2106-Boolean Expressions,双栈运用类似表达式求值!的更多相关文章
- 利用栈实现算术表达式求值(Java语言描述)
利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...
- POJ 2106 Boolean Expressions
总时间限制: 1000ms 内存限制: 65536kB 描述 The objective of the program you are going to produce is to evaluate ...
- 数据结构--栈的应用(表达式求值 nyoj 35)
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=35 题目: 表达式求值 时间限制:3000 ms | 内存限制:65535 KB描述 AC ...
- [poj 2106] Boolean Expressions 递归
Description The objective of the program you are going to produce is to evaluate boolean expressions ...
- POJ 2106 Boolean Expressions (布尔表达式求值)
题意:关于!,&,| 的运算,表达式中V代表true,F代表false. 思路:见代码吧,很详细了. 要注意 !!!F,!(...) 的情况. #include <iostream> ...
- (栈的应用5.2.2)POJ 2106 Boolean Expressions(表达式求值)
/* * POJ_2106.cpp * * Created on: 2013年10月30日 * Author: Administrator */ #include <iostream> # ...
- poj 2106 Boolean Expressions 课本代码
#include<cstdio> const int maxn=100 +10; int val[maxn],vtop; int op[maxn],otop; void insert(in ...
- Dijkstra的双栈算术表达式求值算法
这次来复习一下Dijkstra的双栈算术表达式求值算法,其实这就是一个计算器的实现,但是这里用到了不一样的算法,同时复习了栈. 主体思想就是将每次输入的字符和数字分别存储在两个栈中.每遇到一个单次结束 ...
- 算法手记(2)Dijkstra双栈算术表达式求值算法
这两天看到的内容是关于栈和队列,在栈的模块发现了Dijkstra双栈算术表达式求值算法,可以用来实现计算器类型的app. 编程语言系统一般都内置了对算术表达式的处理,但是他们是如何在内部实现的呢?为了 ...
随机推荐
- 洛谷[LnOI2019]长脖子鹿省选模拟赛t1 -> 快速多项式变换
快速多项式 做法:刚拿到此题有点蒙,一开始真没想出来怎么做,于是试着去自己写几个例子. 自己枚举几种情况之后就基本看出来了,其实本题中 n 就是f(m)在m进制下的位数,每项的系数就是f(m)在m进制 ...
- 1058 合唱队形 2004年NOIP全国联赛提高组
1058 合唱队形 2004年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Descripti ...
- 从零开始利用vue-cli搭建简单音乐网站(四)
上一篇文章中说到这一篇博客会实现音乐播放功能,只是令我意外的是,如果利用h5的audio标签,几行代码就实现了......先来看一下最终效果吧. 这里直接用了audio标签,样式没有怎么管,能获得音乐 ...
- 查找算法(顺序查找、二分法查找、二叉树查找、hash查找)
查找功能是数据处理的一个基本功能.数据查找并不复杂,但是如何实现数据又快又好地查找呢?前人在实践中积累的一些方法,值得我们好好学些一下.我们假定查找的数据唯一存在,数组中没有重复的数据存在. (1)顺 ...
- xml文件解析和序列化
转载:http://blog.csdn.net/liuhe688/article/details/6415593 XmlPullParser parser = Xml.newPullParser(); ...
- 解决在安装Fiddler4.6版本后,在手机上安装证书出现的问题解决方法
解决在安装Fiddler4.6版本后,在手机上安装证书出现的问题解决方法 设置fiddler抓手机包后,在手机上访问http://ip:port,出现如下问题: 问题:creation of the ...
- SQLite-表达式
SQLite -表达式 一个表达式是一个或多个值的组合,运算符和SQL函数,评价一个值. SQL表达式就像公式和都写在查询语言.您还可以使用为特定的数据集查询数据库. 语法: 考虑到SELECT语句的 ...
- 2012-2013 ACM-ICPC, NEERC, Central Subregional Contest C Sequence (打表)
打个表找找规律,到24445的时候乘2以后产生了0出现循环. 一般地,判断循环节是否存在可以用Floyd判圈算法. #include<bits/stdc++.h> using namesp ...
- MIPS汇编程序设计——四则运算计算器
实验目的 运用简单的MIPS实现一个能够整数加减乘除的计算器,同时使自己更加熟悉这些指令吧 MIPS代码 #sample example 'a small calculater’ # data sec ...
- Linux命令权限 用户权限 组权限 文件、目录权限
Linux命令的格式是: 命令+选项+参数 命令是必须存在的,选项和参数可以不必存在,不写的情况是有默认的参数 Linux 一切皆文件 对于文件而言,只需要对文件进行读写就可以实现对文件内容内容的增删 ...