码迷,mamicode.com
首页 > 其他好文 > 详细

表达式求值

时间:2018-09-14 16:00:13      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:dig   contest   break   ==   close   run   strlen   中缀转后缀   using   

以前的:

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 using namespace std;
 5 int lc[10000],rc[10000];
 6 int type[10000];
 7 double data[10000];
 8 char s[10000];
 9 int nc,len,p;
10 bool judge_num(int x,int y)
11 {
12     if(y-x==1&&s[x]==-)   return false;
13     if(s[x]==+||s[x]==*||s[x]==/||s[x]==^)
14         return false;
15     for(int i=x+1;i<y;i++)
16     {
17         if(s[i]==+||s[i]==-||s[i]==*||s[i]==/||s[i]==^)
18             return false;
19     }
20     return true;
21 }
22 int build(int x,int y)
23 {
24     int i,c1=-1,c2=-1,c3=-1,p=0;
25     int u;
26     if(judge_num(x,y)==true)
27     {
28         u=++nc;
29         lc[u]=rc[u]=0;
30         type[u]=0;
31         sscanf(s+x,"%lf",&data[u]);
32         return u;
33     }
34     for(i=x;i<y;i++)
35     {
36         switch(s[i])
37         {
38             case (: p++;break;
39             case ): p--;break;
40             case +: case -: if(!p) c1=i;break;
41             case *: case /: if(!p) c2=i;break;
42             case ^: if(!p) c3=i;break;
43         }
44     }
45     if(c1<0) c1=c2;
46     if(c1<0) c1=c3;
47     if(c1<0) return build(x+1,y-1);
48     u=++nc;
49     lc[u]=build(x,c1);
50     rc[u]=build(c1+1,y);
51     if(s[c1]==+)  type[u]=1;
52     else if(s[c1]==-) type[u]=2;
53     else if(s[c1]==*) type[u]=3;
54     else if(s[c1]==/) type[u]=4;
55     else type[u]=5;
56     return u;
57 }
58 double run(int u)
59 {
60     if(type[u]==1)  return run(lc[u])+run(rc[u]);
61     if(type[u]==2)  return run(lc[u])-run(rc[u]);
62     if(type[u]==3)  return run(lc[u])*run(rc[u]);
63     if(type[u]==4)  return run(lc[u])/run(rc[u]);
64     if(type[u]==5)  return pow(run(lc[u]),run(rc[u]));
65     return data[u];
66 }
67 int main()
68 {
69     scanf("%s",s+1);
70     len=strlen(s+1);
71     p=build(1,len+1);
72     printf("%.3lf",run(p));
73     return 0;
74 }
View Code

写了个O(n)的表达式树...实际要用可能要稍微改一下

http://210.33.19.103/contest/997

中缀转后缀自然是不用的...

技术分享图片
  1 //#pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 using namespace std;
  7 #define fi first
  8 #define se second
  9 #define mp make_pair
 10 #define pb push_back
 11 typedef long long ll;
 12 typedef unsigned long long ull;
 13  
 14 int n,md;
 15 char ss[5001000];
 16  
 17 void do_ub(int x)
 18 {
 19     if(!x)
 20     {
 21         printf("failed:%d\n",x);
 22         int *a=0;*a=234;
 23     }
 24 }
 25 #define assert(x) do_ub(x)
 26  
 27 struct Nd
 28 {
 29     int d;
 30     int type;//0:数字;1:+;2:-;3:*;4:/;5:(;6:)
 31     int num;
 32 };
 33 Nd pre[5001000];
 34 int inv[500100];
 35 int left,plen;
 36 int order[]={3,1,1,2,2};
 37 bool isdigit1(char x){return x>=0&&x<=9;}
 38 int ma[666];
 39  
 40 int an[5001000];
 41 struct TNd
 42 {
 43     int ch[2];
 44     int type;
 45     int d,num;
 46 }nn[5001000];
 47 int mem;
 48 struct ST
 49 {
 50     int st1[10001000],st2[10001000],tp1,tp2;
 51     ST()
 52     {
 53         tp1=0;tp2=1;st2[1]=0;
 54     }
 55     void push(int x)
 56     {
 57         st1[++tp1]=x;
 58     }
 59     bool empty()
 60     {
 61         assert(tp1>=st2[tp2]);
 62         return tp1==st2[tp2];
 63     }
 64     void pop()
 65     {
 66         assert(tp1>st2[tp2]);
 67         if(tp1>st2[tp2]) --tp1;
 68     }
 69     int top()
 70     {
 71         assert(tp1>st2[tp2]);
 72         return st1[tp1];
 73         //return tp1>st2[tp2]?st1[tp1]:0;
 74     }
 75     void add_stack()
 76     {
 77         st2[++tp2]=tp1;
 78     }
 79     void del_stack()
 80     {
 81         assert(tp1==st2[tp2]);
 82         --tp2;
 83     }
 84 }st1,st2;
 85 int calc(int a,int b,int c)
 86 {
 87     if(a==-1||b==-1)    return -1;
 88     switch(c)
 89     {
 90     case 1:
 91         return (a+b)%md;
 92     case 2:
 93         return (a-b+md)%md;
 94     case 3:
 95         return ll(a)*b%md;
 96     case 4:
 97         if(b==0)    return -1;
 98         return ll(a)*inv[b]%md;
 99     default:
100         assert(0);
101         return 0;
102     }
103 }
104 void pop1()
105 {
106     int t1,t2,t3,t;
107     t3=st2.top();st2.pop();
108     t2=st1.top();st1.pop();
109     if(st1.empty())
110     {
111         assert(t3==1||t3==2);
112         t1=0;
113     }
114     else
115     {
116         t1=st1.top();st1.pop();
117     }
118     t=++mem;
119     nn[t].type=t3;
120     nn[t].d=calc(nn[t1].d,nn[t2].d,t3);
121     nn[t].ch[0]=t1;nn[t].ch[1]=t2;
122     st1.push(t);
123 }
124 int len;
125 int calc_r1(int a,int b,int c)//找出x使得a c x = b
126 {
127     if(a==-2||b==-2)    return -2;
128     if(a==-1||b==-1)    return -1;
129     switch(c)
130     {
131     case 1:
132         return calc(b,a,2);
133     case 2:
134         return calc(a,b,2);
135     case 3:
136         if(a==0)    return b==0?-1:-2;
137         return calc(b,a,4);
138     case 4:
139         if(a==0)    return b==0?-1:-2;
140         if(b==0)    return a==0?-1:-2;
141         return calc(a,b,4);
142     default:
143         assert(0);
144         return 0;
145     }
146 }
147 int calc_r2(int a,int b,int c)//找出x使得x c a = b
148 {
149     if(a==-2||b==-2)    return -2;
150     if(a==-1||b==-1)    return -1;
151     switch(c)
152     {
153     case 1:
154         return calc(b,a,2);
155     case 2:
156         return calc(b,a,1);
157     case 3:
158         if(a==0)    return b==0?-1:-2;
159         return calc(b,a,4);
160     case 4:
161         if(a==0)    return -2;
162         return calc(a,b,3);
163     default:
164         assert(0);
165         return 0;
166     }
167 }
168 void solve(int rt,int x)//x为要使得子树成为的值,-1->-1,-2->无解
169 {
170     //printf("t%d %d\n",rt,x);
171     if(nn[rt].type==0)  an[nn[rt].num]=x;
172     else if(!nn[rt].ch[0])  solve(nn[rt].ch[1],calc_r1(0,x,nn[rt].type));
173     else if(!nn[rt].ch[1])  assert(0);//solve(ch[0],x);
174     else
175     {
176         //if(x<0)
177         //printf("%d ch1 %d\n",rt,nn[nn[rt].ch[1]].d);
178         solve(nn[rt].ch[0],calc_r2(nn[nn[rt].ch[1]].d,x,nn[rt].type));
179         //printf("%d ch0 %d\n",rt,nn[nn[rt].ch[0]].d);
180         solve(nn[rt].ch[1],calc_r1(nn[nn[rt].ch[0]].d,x,nn[rt].type));
181     }
182 }
183 int rt;
184 int main()
185 {
186     bool fl=0;
187     int i,edpos=0,nowd,nowdep,t1;
188     ma[+]=1;ma[-]=2;ma[*]=3;ma[/]=4;ma[(]=5;ma[)]=6;
189     scanf("%d%d",&n,&md);
190     inv[1]=1;
191     for(i=2;i<md;i++)    inv[i]=ll(md-md/i)*inv[md%i]%md;
192     scanf("%s",ss+1);len=strlen(ss+1);
193     for(i=1;i<=len;i++)
194     {
195         if(isdigit1(ss[i]))
196         {
197             edpos=i;
198             left=left*10+ss[i]-0;
199         }
200         else
201             break;
202     }
203     nowd=nowdep=0;
204     for(i=edpos+2;i<=len;i++)
205     {
206         if(isdigit1(ss[i]))
207         {
208             fl=1;
209             nowd=nowd*10+ss[i]-0;
210         }
211         else
212         {
213             if(fl)
214             {
215                 fl=0;
216                 ++plen;
217                 pre[plen].d=nowd;pre[plen].type=0;
218                 nowd=0;
219             }
220             ++plen;
221             pre[plen].type=ma[ss[i]];
222         }
223     }
224     if(fl)
225     {
226         ++plen;
227         pre[plen].d=nowd;pre[plen].type=0;
228     }
229     for(i=1;i<=plen;i++)
230     {
231         if(pre[i].type==0&&pre[i].num!=-1)
232         {
233             pre[i].num=++mem;
234             nn[mem].type=0;nn[mem].d=pre[i].d;nn[mem].num=i;
235         }
236     }
237     for(i=1;i<=plen;i++)
238     {
239         if(pre[i].type==5)
240         {
241             st1.add_stack();st2.add_stack();
242         }
243         else if(pre[i].type==6)
244         {
245             while(!st2.empty()) pop1();
246             t1=st1.top();st1.pop();
247             st1.del_stack();st2.del_stack();
248             st1.push(t1);
249         }
250         else if(pre[i].type==0)
251         {
252             st1.push(pre[i].num);
253         }
254         else
255         {
256             while(!st2.empty()&&order[st2.top()]>=order[pre[i].type])
257                 pop1();
258             st2.push(pre[i].type);
259         }
260     }
261     while(!st2.empty())pop1();//{printf("tt%d\n",st2.top());st2.pop();}
262     //while(!st1.empty()){printf("2t%d\n",st1.top());st1.pop();}
263     rt=st1.top();st1.pop();
264     /*
265     for(i=1;i<=mem;i++)
266     {
267         printf("%d %d ",i,nn[i].type);
268         if(nn[i].type==0)   printf("%d ",nn[i].d);
269         else printf("%d %d ",nn[i].ch[0],nn[i].ch[1]);
270         printf("%d ",nn[i].d);
271         puts("");
272     }
273     */
274     solve(rt,left);
275     for(i=1;i<=plen;i++)
276         if(pre[i].type==0)
277         {
278             if(an[i]==-2)   puts("No Solution");
279             else    printf("%d\n",an[i]);
280         }
281     return 0;
282 }
View Code

 

表达式求值

标签:dig   contest   break   ==   close   run   strlen   中缀转后缀   using   

原文地址:https://www.cnblogs.com/hehe54321/p/8044550.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!