传球(概率问题)

来源:互联网 发布:mysql in 值少会索引 编辑:程序博客网 时间:2024/06/05 16:09

传球

问题描述:
N个人坐成一圈, 其中第K个人拿着一个球。 每次每个人会以一定的概率向
左边的人和右边的人传球。 当所有人都拿到过球之后, 最后一个拿到球的人即为胜者。 求第N个人获胜的概率。( 所有人按照编号逆时针坐成一圈)
输入格式:
第一行一个数T代表数据组数。
对于每组数据, 第一行两个整数N, K如题意所述。
接下来每行一个实数p代表该人将球传给右边的人的概率。
输出格式:
对于每组数据, 一行一个实数代表答案, 保留9位小数。
样例输入:
1
5 1
0.10
0.20
0.30
0.40
0.50
样例输出:
0.007692308
数据规模与约定:
对于20%的数据, N ≤ 3。
对于70%的数据, T, N ≤ 100。
对于100%的数据, T ≤ 10000,1 ≤ N ≤ 100。

#include<iostream>#include<cstdio>using namespace std;const int maxn=110;int t,n,k,pre[maxn],next[maxn];long double l[maxn],r[maxn];void deal(int b){    int a=pre[b],c=next[b];    long double ra=r[a]*r[b]/(1-r[a]*(1-r[b]));    long double lc=(1-r[c])*(1-r[b])/(1-(1-r[c])*r[b]);    r[a]=ra;l[a]=1-r[a];l[c]=lc;r[c]=1-l[c];    next[a]=c;pre[c]=a;}long double work(){    if(n<=2) return 1;    if(n<=3) return k==1 ? r[1]:l[2];    for(int i=1;i<=n;i++)    pre[i]=i-1,next[i]=i+1;    pre[1]=n;next[n]=1;    if(k==1)    {        for(int i=2;i<n-1;i++)        deal(i);        return r[1];    }    if(k==n-1)    {        for(int i=2;i<n-1;i++)        deal(i);        return l[n-1];    }    for(int i=2;i<k;i++)    deal(i);    for(int i=k+1;i<n-1;i++)    deal(i);    deal(k);    return l[k]*r[1]+r[k]*l[n-1];}int main(){    freopen("it.in","r",stdin);    freopen("it.out","w",stdout);    cin>>t;    while(t--)    {        cin>>n>>k;        for(int i=1;i<=n;i++)        {            double x;            scanf("%lf",&x);            r[i]=x;            l[i]=1-r[i];        }        printf("%0.9lf\n",(double)work());    }    fclose(stdin);fclose(stdout);    return 0;}
1 0
原创粉丝点击