CodeVS2599 电路的稳定性

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.

你可能感兴趣的:(CodeVS2599 电路的稳定性)