测试题 #4 括号
括号
【问题描述】
有一个长度为?的括号序列,以及?种不同的括号。序列的每个位置上是哪
种括号是随机的,并且已知每个位置上出现每种左右括号的概率。求整个序列是
一个合法的括号序列的概率。
我们如下定义合法括号序列:
? 空序列是合法括号序列;
? 如果?是合法括号序列,那么???是合法括号序列,当且仅当?和?是同种
的左右括号;
? 如果?和?是合法括号序列,那么??是合法括号序列。
【输入格式】
输入第一行包含两个整数?和?。接下来的输入分为?组,每组?行。第?组第
?行包含两个实数?[?,?]和?[?,?],分别代表第?个位置上是第?类的左括号和右括号
的概率。
【输出格式】
输出一行,包含一个实数,代表序列是合法括号序列的概率。建议保留至少
5 位小数输出。只有当你的输出与标准答案之间的绝对误差不超过10 ?5 时,才会
被判为正确。
【样例输入 1】
2 1
1.00000 0.00000
0.00000 1.00000
【样例输出 1】
1.00000
【样例输入 2】
4 1
0.50000 0.50000
1.00000 0.00000
0.00000 1.00000
0.50000 0.50000
测试题 #4 括号
【样例输出 2】
0.25000
【数据规模和约定】
对于20%的数据,? ≤ 50,? = 1,所有位置的概率非 0 即 1。
另外有 30%的数据,? ≤ 34,? = 1,前 10 个和后 10 个位置的所有概率都
是 0.5,中间剩余位置的概率非 0 即 1。
80%的数据,?,? ≤ 50。
对于100%的数据,1 ≤ ? ≤ 200,1 ≤ ? ≤ 50。
1 /*维护两个数组 很好的解决了重复计算的问题*/ 2 #include<iostream> 3 #include<cstdio> 4 #define ld long double 5 #define maxn 210 6 using namespace std; 7 int n,k; 8 ld f[maxn][maxn],ff[maxn][maxn],g[maxn][maxn][2]; 9 int main(){ 10 freopen("brackets.in", "r", stdin); 11 freopen("brackets.out", "w", stdout); 12 cin>>n>>k; 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=k;j++) 15 cin>>g[i][j][0]>>g[i][j][1]; 16 for(int i=1;i<n;i++) 17 for(int x=1;x<=k;x++) 18 f[i][i+1]+=g[i][x][0]*g[i+1][x][1]; 19 for(int i=n-1;i>=1;i--) 20 for(int j=i+3;j<=n;j++){ 21 for(int x=1;x<=k;x++) 22 f[i][j]+=(f[i+1][j-1]+ff[i+1][j-1])*g[i][x][0]*g[j][x][1];// 两头套上一个括号 23 for(int x=i+1;x<j-1;x++) 24 ff[i][j]+=(f[i][x]+ff[i][x])*f[x+1][j]; 25 } 26 printf("%.5f\n",(double)(f[1][n]+ff[1][n])); 27 return 0; 28 }
思路:对于三个连续相同的括号段,枚举会重复,我们定义X从这个位置往后是f数组推出来的,前面的无所谓(由ff数组推出)
时间: 2024-12-26 13:05:05