首页 > 代码库 > 16.1113 模拟考试T2

16.1113 模拟考试T2

测试题 #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数组推出)

16.1113 模拟考试T2