sdutoj 1129 电路稳定性

本文主要探讨ACM竞赛中的1129题——电路稳定性。通过深入理解电路稳定性问题,我们将利用栈来解决后缀表达式计算的问题,进而判断电路的稳定性。详细解析和算法实现尽在文中。
摘要由CSDN通过智能技术生成

题目链接: 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.2
0.3
0.4
0.5
0.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;
}


 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值