NOIP模拟测试15 T3 石头剪刀布

DP神题啊!刚考完试时波波说:“T3改不出来明天就别改了。”

似乎波波已经预料到这题很难改了?

首先设f[i][j][k][o]代表前i+j+k轮选了i个石头,j个布,k个剪刀并且下一个要选o的概率,

然后便可以枚举r(敌人),i,j,k,于是:

可以理解为把这n个人拍在一起

这里o的范围是[0,3],o==0代表的其实是g数组(取i,j,k的概率)

注意要从o转移到o,因为这样可以压行顺便g数组搞出来

有了f数组,接下来考虑如何统计答案:

其实就是把整个过程走一遍,三种情况取max,

最后乘上概率也就是那个组合数。(期望题也是硬伤啊~)

最后注意一下组合数要开long long

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define AA cout<<"Alita"<<endl
 4 #define DD cout<<"Dybala"<<endl
 5 #define m(a) memset(a,0,sizeof(a))
 6 using namespace std;
 7 const int N=55;
 8 int n,C[N][N];
 9 long double tot,p[N][4],f[N][N][N][4],ans;
10 signed main()
11 {
12         //freopen("1.in","r",stdin);
13         scanf("%lld",&n);
14         for(int i=1;i<=n;i++)
15         {
16                 long double x,y,z;
17                 scanf("%Lf%Lf%Lf",&x,&y,&z);
18                 p[i][1]=x/300.0; //石头
19                 p[i][2]=y/300.0; //
20                 p[i][3]=z/300.0; //剪刀
21         }
22         C[0][0]=1;
23         for(int i=1;i<=n;i++)
24         {
25                 C[i][0]=1;
26                 for(int j=1;j<=i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j];
27         }
28         f[0][0][0][0]=1;
29         for(int r=1;r<=n;r++)
30         {
31                 for(int i=r;i>=0;i--)
32                 {
33                         for(int j=r-i;j>=0;j--)
34                         {
35                                 for(int k=r-i-j;k>=0;k--)
36                                 {
37                                         for(int o=3;o>=0;o--)
38                                         {
39                                                 if(r==i+j+k) o=0;
40                                                 if(i) f[i][j][k][o]+=f[i-1][j][k][o]*p[r][1];
41                                                 if(j) f[i][j][k][o]+=f[i][j-1][k][o]*p[r][2];
42                                                 if(k) f[i][j][k][o]+=f[i][j][k-1][o]*p[r][3];
43                                                 if(o) f[i][j][k][o]+=f[i][j][k][0]*p[r][o];
44                                         }
45                                 }
46                         }
47                 }
48         }
49         for(int i=0;i<n;i++)
50         {
51                 for(int j=0;j<n-i;j++)
52                 {
53                         for(int k=0;k<n-i-j;k++)
54                         {
55                                 long double sum=0;
56                                 for(int l=1,p;l<=3;l++)
57                                 {
58                                         if(l==1) p=3;
59                                         else p=l-1;
60                                         sum=max(sum,f[i][j][k][l]+f[i][j][k][p]*3);
61                                 }
62                                 ans+=sum/(double)(C[n][i+j+k]*C[n-i-j-k][1]);
63                         }
64                 }
65         }
66         printf("%0.10Lf",ans);
67         return 0;
68 }

 

 

posted @ 2019-08-09 17:23  ATHOSD  阅读(180)  评论(1编辑  收藏  举报