扑克牌

扑克牌

题目大意,即有54张牌(有大王小王),询问,随机从中抽牌不放回,问得到A张黑桃、B张红桃、C张梅花、D张方块所需抽牌的牌数的期望数,注意抽到的大王和小王可以作为任意一种花色的牌对待,但是所作为的方案,要使最终的期望最小,0<=A,B,C,D<=15。

显然为期望题,显然顺推记概率太麻烦,考虑倒推,于是设(f[a][b][c][d][x][y])已经 抽出a张黑桃,b张红桃,c张梅花,d张方块,大小王状态为x,y
(0表示未抽到,1表示作为黑桃,2红桃,3梅花,4方块) 到达目标状态的数学期望 ,设(sum=a+b+c+d+(x>0)+(y>0)),根据递推套路,我们不难有

[f[a][b][c][d][x][y]=f[a+1][b][c][d][x][y] imesfrac{13-a}{54-sum}+ ]

[f[a][b+1][c][d][x][y] imesfrac{13-b}{54-sum}+f[a][b][c+1][d][x][y] imesfrac{13-c}{54-sum}+ ]

[f[a][b][c+1][d][x][y] imesfrac{13-c}{54-sum}+f[a][b][c][d+1][x][y] imesfrac{13-d}{54-sum}+ ]

[frac{1}{54-sum} imes min_{i=1,!x}^4(f[a][b][c][d][i][y]) ]

[frac{1}{54-sum} imes min_{i=1,!x}^4(f[a][b][c][d][x][i])+1 ]

再根据所需要的牌数作为边界,注意大小王的影响,故边界不简简单单地为(f[A][B[C][D][?][?]=0),答案不难得知为(f[0][0][0][0][0][0]),根据递推方程转移即可。

参考代码:

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define db double
#define exact 0.001
using namespace std;
int A,B,C,D;
db dp[14][14][14][14][5][5];
il db dfs(int,int,int,int,int,int);
il bool check(int,int,int,int,int,int);
template<class free>il free Min(free,free);
int main(){
    int check(0);
    scanf("%d%d%d%d",&A,&B,&C,&D);
    if(A>13)check+=A-13;if(B>13)check+=B-13;
    if(C>13)check+=C-13;if(D>13)check+=D-13;
    if(check>2)puts("-1.000");
    else printf("%.3lf",dfs(0,0,0,0,0,0));
    return 0;
}
template<class free>
il free Min(free a,free b){
    return a<b?a:b;
}
il db dfs(int a,int b,int c,int d,int x,int y){
    db &ans=dp[a][b][c][d][x][y];
    if(ans>exact)return dp[a][b][c][d][x][y];
    if(check(a,b,c,d,x,y))return 0;
    int rest(54-(a+b+c+d+(x>0)+(y>0)));
    if(a<13)ans+=dfs(a+1,b,c,d,x,y)*(13-a)/rest;
    if(b<13)ans+=dfs(a,b+1,c,d,x,y)*(13-b)/rest;
    if(c<13)ans+=dfs(a,b,c+1,d,x,y)*(13-c)/rest;
    if(d<13)ans+=dfs(a,b,c,d+1,x,y)*(13-d)/rest;
    if(!x)ans+=Min(Min(dfs(a,b,c,d,1,y),dfs(a,b,c,d,2,y)),
                    Min(dfs(a,b,c,d,3,y),dfs(a,b,c,d,4,y)))/rest;
    if(!y)ans+=Min(Min(dfs(a,b,c,d,x,1),dfs(a,b,c,d,x,2)),
                    Min(dfs(a,b,c,d,x,3),dfs(a,b,c,d,x,4)))/rest;
    return ++ans;
}
il bool check(int a,int b,int c,int d,int x,int y){
    if(x==1)++a;else if(x==2)++b;else if(x==3)++c;else if(x==4)++d;
    if(y==1)++a;else if(y==2)++b;else if(y==3)++c;else if(y==4)++d;
    if(a>=A&&b>=B&&c>=C&&d>=D)return true;else return false;
    
}
原文地址:https://www.cnblogs.com/a1b3c7d9/p/10812355.html