ZOJ 4021 Boolean Expression(模拟)

Boolean Expression


Time Limit: 1 Second      Memory Limit: 65536 KB


Given a valid boolean expression consisting of seven types of characters 'T' (true), 'F' (false), '!' (not), '&' (and), '|' (or), '(' (left bracket) and ')' (right bracket), you can add any number of these seven types of characters into the expression to make it true (of course, the expression must still be valid).

Please calculate the minimum number of characters you have to add into the expression to make it true.

The priority of the boolean operators are: '!' > '&' > '|', just the same as their priority in most of the programming languages.

To be specific, a valid boolean expression can be expressed by the following BNF,

<bool> ::= 'T' | 'F' | '(' <expr> ')'
<not-expr> ::= '!' <not-expr> | <bool>
<and-expr> ::= <and-expr> '&' <not-expr> | <not-expr>
<expr> ::= <expr> '|' <and-expr> | <and-expr>

where <expr> is a valid boolean expression.

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first and only line contains a boolean expression  () without space consisting of 'T', 'F', '!', '&', '|', '(' and ')'.

It's guaranteed that the given expression is valid, and the sum of  over all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the minimum number of characters you have to add into the expression to make it true.

Sample Input

4
!T&F
T&!F|T&F
(T&(!T|(!!F))&T)
!!!!!F

Sample Output

2
0
1
0

Hint

For the first sample test case, we can add a pair of brackets and change the expression to !(T&F).

For the second sample test case, note that the priority of '&' is higher than '|', so the original expression is already true.

For the third sample test case, we can add a '!' and change the expression to !(T&(!T|(!!F))&T).

We kindly remind you that the stack size of the online judge system is limited to 8M, so please use your stack space wisely.

题意:

给你一个由&|()!TF构成的表达式(长度<=5e5),T为1,F为0,求使表达式的值变为真最少需要添加的字符数(只能填给的这7种字符)。

思路:

容易想到答案的上界是2,即加上|T。0的情况我们可以直接栈模拟来判断表达式的值,需要讨论的便是1的情况。

考虑将表达式化简。化成x&x|x&x&x|x的形式,即x=0,1,两两之间只有&和|相连。

任意两个|之间的x如果全为1,则表达式即为真,不需要再添加字符。

任意两个|之间的x如果只有一个0,则表达式只需要添加一个字符即可变为真(x变成!x)。

否则,答案就是2(|T)。

代码:(调了两天总算过了。。。)

#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<set>
#define inf 0x3f3f3f3f
#define ll long long
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=500010;
int n,m,k;
int stk[maxn],cnt;
char s[maxn];
int a[maxn],ct,c[maxn];
int x,y,z;
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        int l=strlen(s);
        s[l]='|';
        int tmp=0;ct=0;
        cnt=0;
        y=1;
        rep(i,0,l-1)
        {
            if(s[i]=='!') tmp^=1;
            else if(s[i]=='T'||s[i]=='F')
            {
                if(s[i]=='T') x=1;
                else x=0;
                if(tmp) x^=1;
                tmp=0;
                if(!cnt)
                {
                    a[++ct]=x;
                    if(s[i+1]=='&') a[++ct]=4;
                    else a[++ct]=3;
                    i++;
                }
                else
                {
                    if(stk[cnt]==4)
                    {
                        stk[cnt-1]=(x&stk[cnt-1]);
                        cnt--;
                    }
                    else if(stk[cnt]==3||stk[cnt]==2)
                    {
                        stk[++cnt]=x;
                    }
                }
            }
            else if(s[i]=='|') stk[++cnt]=3;
            else if(s[i]=='&') stk[++cnt]=4;
            else if(s[i]=='(') {stk[++cnt]=2;c[cnt]=tmp;tmp=0;}//注意括号前面的!
            else
            {
                y=stk[cnt--];
                while(stk[cnt]!=2)
                {
                    if(stk[cnt]==4)
                    y&=stk[cnt-1];
                    else y|=stk[cnt-1];
                    cnt-=2;
                }
                if(c[cnt]) y^=1;//
                if(cnt==1)
                {
                    cnt=0;
                    a[++ct]=y;
                    if(s[i+1]=='&') a[++ct]=4;
                    else a[++ct]=3;
                    i++;
                }
                else
                {
                    stk[cnt]=y;
                    if(stk[cnt-1]==4)//这个地方特别注意,括号出栈时&要直接运算(优先级高)
                    {
                        stk[cnt-2]&=y;
                        cnt-=2;
                    }
                }
            }
        }
        //rep(i,1,ct)
        //printf("%d",a[i]);
        //cout<<endl;
        x=0;y=0;
        int fg=0,fg2=0;
        rep(i,1,ct)
        {
            if(i&1)
            {
                if(a[i]) x++;
                else y++;
            }
            else if(a[i]==3)
            {
                 if(y==0&&x) {fg=1;}
                 if(y==1) fg2=1;
                 x=0;y=0;
            }
        }
        if(fg) puts("0");
        else if(fg2) puts("1");
        else puts("2");
    }
    return 0;
}
/*
100
!T&F
T&!F|T&F
(T&(!T|(!!F))&T)
!!!!!F
T&!(F|T)&F|(T&(!T|(!!F))&T)
T&!(F|T)
!T&!(F|T)
F&(F)
T&(F)
T&(F|F)
!T&!(F|T)&F|!!!(F)&!(T&(!T|(!!F))&T)
!(T&F)|(F&F)
(T&!F&!!T|F&(!!F))
F&!F|F&T|F&T
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值