题解:P2413 yyy loves physics IV
AC记录
题意
给你一个电路,电路中的元件有一个损坏的概率,求整个电路断路的概率。
分析
令
于是就把题目变成了表达式求值。
首先应匹配括号。用一个栈,每次遇到左括号就压入,遇到右括号就让栈顶括号匹配当前括号。
#define ll long long
...
stack<ll>q;
...
for(ll i=1;i<=m;i++)
if(s[i]=='(')q.push(i);
else if(s[i]==')')
{
f[q.top()]=i;
q.pop();
}
然后分治处理表达式。
double dfs(ll x,ll y)//处理s[x..y]
{
if(f[x]==y)//如果x和y匹配就把括号去掉
{
x++;y--;
}
if(x==y&&isalpha(s[x]))return a[s[x]-64];
//如果只有一个元件就返回其损坏概率
ll k=0;
for(ll i=x;i<=y;i++)
{
if(s[i]=='(')k++;
else if(s[i]==')')k--;
if(k==0&&s[i]==',')return 1-(1-dfs(x,i-1))*(1-dfs(i+1,y));
//找到串联的地方,分治解决两边
}
for(ll i=x;i<=y;i++)
{
if(s[i]=='(')k++;
else if(s[i]==')')k--;
if(k==0&&s[i]==')'&&s[i+1]=='('&&i!=y)return dfs(x+1,i-1)*dfs(i+1,y);
//找并联的地方
}
return 1;
}
所求就是 dfs(1,n)。
完整程序
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=100010;
ll n,m;
ll f[N];
double a[N];
string s;
stack<ll>q;
double dfs(ll x,ll y)
{
if(f[x]==y)
{
x++;y--;
}
if(x==y&&isalpha(s[x]))return a[s[x]-64];
ll k=0;
for(ll i=x;i<=y;i++)
{
if(s[i]=='(')k++;
else if(s[i]==')')k--;
if(k==0&&s[i]==',')return 1-(1-dfs(x,i-1))*(1-dfs(i+1,y));
}
for(ll i=x;i<=y;i++)
{
if(s[i]=='(')k++;
else if(s[i]==')')k--;
if(k==0&&s[i]==')'&&s[i+1]=='('&&i!=y)return dfs(x+1,i-1)*dfs(i+1,y);
}
return 1;
}
int main()
{
scanf("%lld",&n);
cin>>s;
s=" "+s;
m=s.size()-1;
for(ll i=1;i<=n;i++)
scanf("%lf",&a[i]);
for(ll i=1;i<=m;i++)
if(s[i]=='(')q.push(i);
else if(s[i]==')')
{
f[q.top()]=i;
q.pop();
}
printf("%.4f",dfs(1,m));
}