您的位置:首页 > 其它

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

2016-03-30 17:26 316 查看
洛谷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
='#'; s[++n]='\0';
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 */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: