• 【数据结构】P1310 表达式的值


    【题目链接】

    https://www.luogu.org/problem/P1310

    题目描述

    对于1 位二进制变量定义两种运算:

    运算的优先级是:

    1. 先计算括号内的,再计算括号外的。

    2. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算。例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算。

    现给定一个未完成的表达式,例如_+(_*_),请你在横线处填入数字00或者11 ,请问有多少种填法可以使得表达式的值为00。

    输入格式

    共 2 行。

    第1 行为一个整数 LL,表示给定的表达式中除去横线外的运算符和括号的个数。

    第2 行为一个字符串包含 LL 个字符,其中只包含’(’、’)’、’+’、’*’这44 种字符,其中’(’、’)’是左右括号,’+’、’*’分别表示前面定义的运算符“⊕”和“×”。这行字符按顺序给出了给定表达式中除去变量外的运算符和括号。

    输出格式

    共1 行。包含一个整数,即所有的方案数。注意:这个数可能会很大,请输出方案数对1000710007取模后的结果。

    输入输出样例

    输入 #1
    4
    +(*)
    
    输出 #1

    说明/提示

    【输入输出样例说明】

    给定的表达式包括横线字符之后为:_+(_*_)

    在横线位置填入(0 、0 、0) 、(0 、1 、0) 、(0 、0 、1) 时,表达式的值均为0 ,所以共有3种填法。

    【题解】

    1、转变为后缀表达式的形式,然后,如果是操作数要添加一个数字,记住第一个位置要多添加一个‘.’

    2、然后进行推导,把四种情况的转移状态写清楚。

    参考题解中duyi 

    第一步:中缀转后缀

    后缀表达式是什么呢?参见洛谷P1449

    这里先给大家介绍一下中缀表达式转后缀表达式的一般方法:

    中缀表达式a + b*c + (d * e + f) * ga+bc+(de+f)g,其转换成后缀表达式则为a b c * + d e * f + g * +abc+def+g+。

    转换过程需要用到栈,具体过程如下:

    1)如果遇到操作数,我们就直接将其输出。

    2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

    3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

    4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

    5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

    备注:本题中我们用一个"."来代表数字。扫描整个表达式(读入的字符串),如果当前位置不是括号(既不是左括号也不是右括号),就在后缀表达式里填一个"."表示这里应有一个数字。

    第二步:DP

    状态转移方程很好想:

    如果当前是"*":

    f[0][now]=f[0][now]f[0][last]+f[0][now]f[1][last]+f[1][now]f[0][last]

    f[1][now]=f[1][now]f[1][now]

    (注意两式顺序不能颠倒,因为1式中需要用到f[1][now]f[1][now]的原始值)

    如果当前是"+":

    f[1][now]=f[1][now]f[1][last]+f[0][now]f[1][last]+f[1][now]f[0][last]

    f[0][now]=f[0][now]f[1][last]

    (两式的顺序同样不能颠倒)

    其中,f[i][j]表示j号数字是i的情况有多少种,初始化为1


    【代码】

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int mod = 10007 ;
     4 const int N = 1e5+10;
     5 
     6 int f[2][N] ;
     7 
     8 int priority( char s ){
     9     switch ( s ){
    10         case '+' : return 1 ;
    11         case '*' : return 2 ;
    12         case '(' :
    13         case ')' : return -1;
    14     }
    15 }
    16 
    17 void toSuffixString( string &s ){
    18     int len = s.length();
    19 
    20     string res = "." ;
    21     stack < int > Op ;
    22 
    23     for(int i=0;i<len ;i++){
    24         /*if( s[i] == '.') {
    25             res += ".";
    26         }else */
    27         if( s[i] == '(' || s[i] == '*' ){
    28             Op.push(s[i]);
    29         }else if( s[i] == ')' ){
    30             while( !Op.empty() && Op.top() != '(' ){
    31                 res += Op.top();
    32                 Op.pop();
    33             }
    34             //出来的时候,栈顶为(.
    35             Op.pop();
    36         }else{
    37             while( !Op.empty() && priority(Op.top()) >= priority(s[i]) ){
    38                 res += Op.top();
    39                 Op.pop();
    40             }
    41             //出来的时候,栈里面的运算符优先级低于当前位置.
    42             Op.push( s[i] ) ;
    43         }
    44         if( !(s[i] == '(' || s[i] == ')') ){
    45             res += ".";
    46         }
    47     }
    48     while( !Op.empty() ){
    49         res += Op.top();
    50         Op.pop();
    51     }
    52     //cout << res << endl ;
    53     s = res ;
    54 }
    55 
    56 void Calc( string s ){
    57     //cout << s << endl ;
    58     int j = 0 ;
    59     int len = s.length();
    60     for(int i=0 ; i < len ; i++ ){
    61         if( s[i] == '.' ){
    62             j ++ ;
    63             f[0][j] = f[1][j] = 1 ;
    64         }else if( s[i] == '*' ){
    65             j -- ;
    66             f[0][j] =(f[1][j] * f[0][j+1] +
    67                       f[0][j] * f[1][j+1] +
    68                       f[0][j] * f[0][j+1] ) % mod ;
    69 
    70             f[1][j] = (f[1][j] * f[1][j+1]) % mod ;
    71 
    72         }else if( s[i] == '+' ){
    73             j -- ;
    74             f[1][j] =(f[1][j] * f[0][j+1] +
    75                       f[0][j] * f[1][j+1] +
    76                       f[1][j] * f[1][j+1] ) % mod ;
    77 
    78             f[0][j] =(f[0][j] * f[0][j+1] ) %mod ;
    79         }
    80     }
    81     cout << f[0][1] << endl;
    82 }
    83 
    84 int main(){
    85     ios_base :: sync_with_stdio( false );
    86     cin.tie(NULL) , cout.tie(NULL) ;
    87     int n ;
    88     string str ;
    89     cin >> n >> str ;
    90     toSuffixString(str);
    91     Calc(str);
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    VS 2010 C#入门操作小技巧
    spring-data-jpa 多数据源
    Spring--3.Spring的单元测试
    Spring--5.IOC总结
    Spring--4.实验23.IOC容器的测试泛型依赖注入*
    Spring--2.Spring之IOC--IOC容器的22个实验(3)
    Spring--2.Spring之IOC--IOC容器的22个实验(2)
    Spring--2.Spring之IOC--IOC容器的22个实验(1)
    Spring--2.Spring之IOC--了解IOC容器
    Spring--1.了解Spring
  • 原文地址:https://www.cnblogs.com/Osea/p/11380771.html
Copyright © 2020-2023  润新知