洛谷1310 表达式的值【探讨】

洛谷1310 表达式的值

本题地址: http://www.luogu.org/problem/show?pid=1310

题目描述

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

  运算的优先级是: 
  1. 先计算括号内的,再计算括号外的。 
  2. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算。例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算。 
  现给定一个未完成的表达式,例如_+(_*_),请你在横线处填入数字0 或者1 ,请问有多少种填法可以使得表达式的值为0 。

输入输出格式

输入格式:

  输入文件名为exp.in ,共 2 行。 
  第1 行为一个整数 L,表示给定的表达式中除去横线外的运算符和括号的个数。 
  第2 行为一个字符串包含 L 个字符,其中只包含’(’、’)’、’+’、’*’这4 种字符,其中’(’、’)’是左右括号,’+’、’*’分别表示前面定义的运算符“⊕”和“×”。这行字符按顺序给出了给定表达式中除去变量外的运算符和括号。

输出格式:

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

输入输出样例

输入样例#1:

4

+(*)

输出样例#1:

说明

【输入输出样例说明】 
  给定的表达式包括横线字符之后为:_+(_*_) 
  在横线位置填入(0 、0 、0) 、(0 、1 、0) 、(0 、0 、1) 时,表达式的值均为0 ,所以共有3种填法。 
【数据范围】 
对于20% 的数据有 0 ≤ L ≤ 10。 
对于50% 的数据有 0 ≤ L ≤ 1,000。 
对于70% 的数据有 0 ≤ L ≤ 10,000 。 
对于100%的数据有 0 ≤ L ≤ 100,000。 
对于50% 的数据输入表达式中不含括号。

【探讨】

   表达式树建立+树上DP。

   对于DP而言,设d[i][j]为根结果为j的数目,j==0||j==1,有如下递推式:

     略,见代码。

   对于建立表达式而言,因为L已经到了10^5所以必须要采用有效快速的方法,我用的是递归建树的方法,时间为O(n^2),撑不起来只能过8个点。

   至于O(n)的算法,留待以后研究一下。

【代码】

  1 #include<iostream>
  2 #include<cstring>
  3 #include<stack>
  4 #include<fstream> 
  5 using namespace std;
  6 
  7 const int maxn = 100000+10;
  8 const int MOD=10007;
  9 
 10 int lch[maxn],rch[maxn]; char op[maxn];
 11 int nei[333],wai[333];
 12 int d[maxn][2];
 13 string s;
 14 int n,nc=0;
 15 
 16 inline char cmp(char a,char b) {
 17     if(nei[a]>wai[b]) return '>';
 18     else if(nei[a]<wai[b]) return '<';
 19     else return '=';
 20 }
 21 
 22 void dp(int u) {
 23     if(d[u][0]) return ;
 24     
 25     if(!lch[u] && !rch[u]) {  //op=='_'
 26          d[u][1]=d[u][0]=1;
 27          return ;
 28     }
 29     
 30     dp(lch[u]); 
 31     dp(rch[u]);
 32     
 33     if(op[u]=='+') {
 34          d[u][0]=d[lch[u]][0]*d[rch[u]][0];
 35          d[u][1]=d[lch[u]][0]*d[rch[u]][1] + d[lch[u]][1]*d[rch[u]][0] + d[lch[u]][1]*d[rch[u]][1];
 36     }
 37     else {
 38          d[u][0]=d[lch[u]][0]*d[rch[u]][1] + d[lch[u]][1]*d[rch[u]][0] + d[lch[u]][0]*d[rch[u]][0];
 39          d[u][1]=d[lch[u]][1]*d[rch[u]][1];
 40     }
 41     d[u][0]%=MOD;
 42     d[u][1]%=MOD;
 43 }
 44 
 45 int build_tree(int ,int);
 46 
 47 int main() {
 48     cin>>n>>s;
 49     int root=build_tree(0,n);
 50     dp(root);
 51     cout<<d[root][0];
 52     return 0;
 53 }
 54 
 55 int build_tree(int x,int y) {  //[x,y)
 56     int u,c1=-1,c2=-1,p=0;
 57     
 58     if(y<=x) {                //y<=x
 59         u=++nc;
 60         op[u]='_';
 61         lch[u]=rch[u]=0;
 62         return u;
 63     }
 64     
 65     for(int i=x;i<y;i++) 
 66        switch(s[i]) {
 67                case '(': p++; break;
 68                case ')': p--; break;
 69                case '+': if(!p) c1=i; break;
 70                case '*': if(!p) c2=i; break;
 71        }
 72     if(c1<0) c1=c2;
 73     if(c1<0) return build_tree(x+1,y-1);
 74     
 75     u=++nc;
 76     lch[u]=build_tree(x,c1);
 77     rch[u]=build_tree(c1+1,y);
 78     op[u]=s[c1];
 79     return u;
 80 }
 81 
 82 //a failed experience
 83 /*
 84 int build_tree() {
 85     s[n]='#'; s[++n]='';
 86     stack<int> opint; stack<char> opchar;
 87     opchar.push('#');
 88     
 89     op[n+10]='_'; lch[n+1]=rch[n+1]=0;  //定义数字节点
 90     
 91     nei['+']=2; wai['+']=1;
 92     nei['*']=4; wai['*']=3;
 93     nei[')']=8; wai[')']=0;
 94     nei['(']=0; wai['(']=8;
 95     nei['#']=-1; wai['#']=-1;
 96     
 97     int i=0,u;
 98     while(opchar.top()!='#' || s[i]!='#')
 99     {
100         switch(cmp(opchar.top(),s[i])) {
101             case '<' : opchar.push(s[i]); i++; break;
102             case '=' : opchar.pop(); i++;  break;
103             case '>' :
104                 u=++nc;
105                 lch[u]=rch[u]=n+1;
106                 op[u]=opchar.top();
107                 
108                 int f=0;
109                 if(opint.size()>=2-f){
110                     lch[u]=opint.top(); 
111                     opint.pop();
112                     f++;
113                 }
114                 
115                 if(opint.size()>=2-f){
116                     rch[u]=opint.top(); 
117                     opint.pop();
118                 }
119                 
120                 opint.push(u);
121                 opchar.pop();
122                 
123                 break;
124         }
125     }
126     return opint.top();
127 }
128 */
原文地址:https://www.cnblogs.com/lidaxin/p/4890359.html