題目連結: sdutoj 1129 電路穩定性
/*【題目描述】Heinz有一個電路,電路上有n個元件。已知元件i損壞而斷開的機率是Pi(i=1,2,...,n,0≤pi≤1)。請你幫Heinz算出整個電路斷路的機率。元件的串連方式很簡單,對電路的表示如下:(1)一個元件是最小的電路,用A表示元件1,B表示元件2,如此類推。(2)k個電路組成的串聯電路表示為電路1,電路2,......,電路k。注串聯電路用“,”號隔開。(3)k個電路組成的並聯電路表示為(電路1)(電路2)......(電路k)。注並聯電路用“( )”標示。對於兩個電阻,如果它們斷開的機率是P(i)和P(j)時,有:(1)如果它們是並聯電路,則斷開的機率是P(i)*P(j)。(2)如果它們是串聯電路,則斷開的機率是P(i)+(1-P(i))*P(j)。【輸入】第1行是一個整數n(2≤n≤26),表示一共有多少個元件;第2行是表示電路的字串;最後是n行,每行是一個實數Pi(i=1,2,...,n,0≤pi≤1),表示該元件斷路的機率。【輸出】輸出一個實數,表示整個電路斷路的機率,精確到小數點後4位。【樣本輸入】5(A,B)((C)(D),E)0.20.30.40.50.6【樣本輸出】把電路字串先變成中綴運算式的形式,再變成尾碼運算式,然後求值0.2992*/#include <cstdio>#include <cstring>#include <iostream>#include <string>#include <stack>using namespace std;double p[27]; //每個元件斷路的機率double BingLian(double x, double y); //並聯機率double ChuanLian(double x, double y); //串聯機率int main(){ stack<char> circuit; //電路棧 stack<double> GaiLv; //求機率 int n; //n個元件 char strCircuit[105]; //電路字串 char strZhongZhui[205]; //中綴運算式 char strHouZhui[205]; //尾碼運算式 double total; //電路斷路的機率 int len; //中綴和尾碼運算式的長度 int i,j; //輸入 scanf("%d", &n); cin >> strCircuit; for (int i=1; i<=n; i++) { cin >> p[i]; } //轉換成中綴運算式,把逗號變加號,這樣的括弧 ')(' 變成 ')*(' j = strlen(strCircuit); len = 0; for (i=0; i<j; i++) { if ((i+1<j) && strCircuit[i] == ')' && strCircuit[i+1] == '(') { strZhongZhui[len++] = strCircuit[i]; strZhongZhui[len++] = '*'; } else { if (strCircuit[i] == ',') { strZhongZhui[len++] = '+'; } else { strZhongZhui[len++] = strCircuit[i]; } } } strZhongZhui[len] = '\0'; //printf("%s\n", strZhongZhui); //中綴轉成尾碼運算式,好計算 for (i=0, j=0; i<len; i++) { if (strZhongZhui[i] == '(') //左括弧直接進棧 { circuit.push('('); } //字元直接進尾碼運算式數組中 else if ((strZhongZhui[i] >= 'A') && (strZhongZhui[i] <= 'Z')) { strHouZhui[j++] = strZhongZhui[i]; } //右括弧從棧中取操作符存入尾碼運算式,直到遇到左括弧 else if (strZhongZhui[i] == ')') { while (circuit.top() != '(') { strHouZhui[j++] = circuit.top(); circuit.pop(); } circuit.pop(); } //操作符優先順序比棧頂高的直接進棧,如果優先順序<=棧頂元素,就把棧頂元素存入尾碼運算式 //直到棧頂元素的優先順序低於操作符,則此操作符入棧, else { if (strZhongZhui[i] == '+' && circuit.empty()) { circuit.push('+'); } else if (strZhongZhui[i] == '+') { while (circuit.top() != '(') { strHouZhui[j++] = circuit.top(); circuit.pop(); } circuit.push('+'); } else if (strZhongZhui[i] == '*' && circuit.empty()) { circuit.push('*'); } else { while (circuit.top() == '*') { strHouZhui[j++] = '*'; circuit.pop(); } circuit.push('*'); } } } while (!circuit.empty()) { strHouZhui[j++] = circuit.top(); circuit.pop(); } strHouZhui[j] = '\0'; //printf("%s", strHouZhui); //計算尾碼運算式,就是把字元轉換成機率 for (i=0; i<j; i++) { if ((strHouZhui[i] >= 'A') && (strHouZhui[i] <= 'Z')) { GaiLv.push(p[strHouZhui[i]-'A' + 1]); } else { if (strHouZhui[i] == '+') //加號代表串聯 { double first = GaiLv.top(); //棧第一個值 GaiLv.pop(); double second = GaiLv.top(); //棧第二個值 total = ChuanLian(first, second); //求出這兩個元件串聯的機率 GaiLv.top() = total; //修改棧頂值 } else //並聯,原理和串聯一樣 { double first = GaiLv.top(); GaiLv.pop(); double second = GaiLv.top(); total = BingLian(first, second); GaiLv.top() = total; } } } total = GaiLv.top(); printf("%.4lf\n", total); return 0;}//並聯機率double BingLian(double x, double y){ return x*y;}//串聯機率double ChuanLian(double x, double y){ return x+(1.0-x)*y;}