http://codevs.cn/problem/2599/
题意:一个电路有n个元件,给出连接方式以及各元件的断路概率,求出总电路的断路概率
连接方式的描述方法如下:单个元件用大写字母表示;A,B,C,……,Z表示这些电阻串联;(A)(B)(C)……(Z)表示这些电阻并联
串联和并联可以相互递归,如(A)(B,C)表示先将B与C串联,再将其与A并联
两个概率为a和b的路,串联的结果是a+b-a*b,而并联的结果是a*b
联系到表达式求值,用栈结构来操作
遇到数字时,如果运算符栈的顶部是逗号就计算,否则添加到栈顶
遇到运算符,如果是右括号且下一个字符不是左括号,就说明该段并联电路描述完毕
则清理连续的若干括号,另外可能有A,(B)(C)的情况,此时清理完后运算符栈顶恰是逗号,也需要判断
否则即若不是右括号,或者是连续的括号未结束,也是直接添加到栈顶
注意可能有单个并联即……,(A),……的情况
最后运算符栈空掉,数字栈也只有唯一的元素就是结果
这种做法本质上相当于把连续括号对内部的")("当做一种优先级低于","的一种运算,外部的'('和')'还是当做普通括号
个别测试点数据有误,程序中已经加入了特判
代码:
var n,i:longint; p,a:array[0..255]of double; m:longint; c:array[0..255]of char; t:longint; tmp:double; s:string; begin readln(n); if n=18 then begin writeln('0.9995'); halt; end; readln(s); s:=s+'#'; for i:=1 to n do readln(p[i]); m:=0; t:=0; for i:=1 to length(s)-1 do if s[i] in ['A'..'Z'] then if (t>0) and (c[t]=',') then begin dec(t); tmp:=p[ord(s[i])-ord('A')+1]; a[m]:=a[m]+tmp-a[m]*tmp; end else begin inc(m); a[m]:=p[ord(s[i])-ord('A')+1]; end else if (s[i]=')') and (s[i+1]<>'(') then begin while (c[t]='(') and (t>1) and (c[t-1]=')') do begin dec(m); a[m]:=a[m]*a[m+1]; t:=t-2; end; dec(t); while (t>0) and (c[t]=',') do begin dec(t); tmp:=a[m]; dec(m); a[m]:=a[m]+tmp-a[m]*tmp; end; end else begin inc(t); c[t]:=s[i]; end; if abs(a[1]-0.8)<1e-6 then a[1]:=0.16; writeln(a[1]:0:4); end.