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,

 ::= 'T' | 'F' | '('  ')'
 ::= '!'  | 
 ::=  '&'  | 
 ::=  '|'  | 

where 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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<

 

你可能感兴趣的:(其他:模拟,其他:思维)