HNOI2015 亚瑟王

Description

 

Input

Output


 

Sample Input

输入1:
1
3 2
0.5000 2
0.3000 3
0.9000 1
输入2:
1
10 12
0.3668 857
0.4736 283
0.2321 801
0.6880 555
0.0225 121
0.5814 724
0.0456 60
0.9827 561
0.7015 962
0.1746 960

Sample Output

输出1:
3.2660250000
输出2:
5279.3753475918
 

Data Constraint

 
在分析题目之后,我们发现我们实际要求的其实只是每张牌发动技能的期望,它是在哪一轮发动不需考虑。
然后我们可以将题目稍做转换,有r个机会,n个人,第i的人得到机会的概率为pi.
我们可以设f[i][j]表示考虑完前i个人,还有j次机会的概率。
那么有两种转移方式:
1.第i+1个人没有得到机会,则f[i+1][j]+=f[i][j]*(1-pi+1)^j
2.第i+1个人得到一次机会,则f[i+1][j]+=f[i][j]*(1-(1-pi+1)^j));因为根据题意每个人最多得到一次机会,所以尽管可能有分到多次机会的概率,我们仍按一次来算,在这个转移可顺便求出每个人得到机会的概率。
 
时间复杂度O(nrT)
 
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>

using namespace std;

int dt,tj,i,n,m,j;
double ans;

struct card{
    double p,d;
}a[231];

double d[231],f[231][231],p[231][231];

int main()
{
    scanf("%d",&dt);
    for(tj=1;tj<=dt;tj++){
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].p,&a[i].d);
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        f[m][0]=1;
        for(i=1;i<=n;i++)p[i][1]=1-a[i].p;
        for(i=2;i<=m;i++)
            for(j=1;j<=n;j++)p[j][i]=p[j][i-1]*(1-a[j].p);
        for(i=m;i>=1;i--){
            for(j=0;j<n;j++){
                f[i][j+1]+=f[i][j]*p[j+1][i];
                f[i-1][j+1]+=f[i][j]*(1-p[j+1][i]);
                d[j+1]+=f[i][j]*(1-p[j+1][i]);
            }
        }
        ans=0;
        for(i=1;i<=n;i++)ans+=a[i].d*d[i];
        printf("%.11lf
",ans);
    }
}
原文地址:https://www.cnblogs.com/applejxt/p/4450533.html