LightOJ 1364 Expected Cards 期望DP+记忆化搜索

Expected Cards LightOJ - 1364

5454 张牌,其中♣ ♦ ♥ ♠ 各有 1313 张,还有两张大小王,现在从洗好的牌里依次抽,问抽到至少 CC 张梅花,DD 张方片,HH 张红桃,SS 张黑桃所需要抽的期望张数是多少?假如抽到大小王的话,可以令他们为任意的花色,但是必须立刻指定他们的花色,不能随后更改。

dp[c][d][h][s][i][j]dp[c][d][h][s][i][j] 表示当前抽到的四个花色数量分别是 c,d,h,sc,d,h,s 时,并且小王大王分别处于 i,ji,j 状态时(i=0i=0表示还未抽到,i=14i=1\sim 4 表示已经抽到,代替四种花色之一)对应的期望。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
//#define WINE
#define INF 0x3f3f3f3f
using namespace std;
int T,iCase,a[5],b[5];
double res,dp[14][14][14][14][5][5];
bool check(int c,int d,int h,int s,int p,int q){
    memset(b,0,sizeof(b));
    b[1]=c;b[2]=d;b[3]=h;b[4]=s;b[p]++;b[q]++;
    for(int i=1;i<=4;i++)
        if(b[i]<a[i])return false;
    return true;
}
double dfs(int c,int d,int h,int s,int p,int q){
    if(check(c,d,h,s,p,q))return dp[c][d][h][s][p][q]=0;
    if(dp[c][d][h][s][p][q]>=0)return dp[c][d][h][s][p][q];
    int sum=54-c-d-h-s;
    if(p)sum--;if(q)sum--;
    if(sum==0)return 0;
    double res=0;
    if(c<13)res+=dfs(c+1,d,h,s,p,q)*(13-c)/sum;
    if(d<13)res+=dfs(c,d+1,h,s,p,q)*(13-d)/sum;
    if(h<13)res+=dfs(c,d,h+1,s,p,q)*(13-h)/sum;
    if(s<13)res+=dfs(c,d,h,s+1,p,q)*(13-s)/sum;
    if(!p){
        double tmp=INF;
        for(int i=1;i<=4;i++)
            tmp=min(tmp,dfs(c,d,h,s,i,q));
        res+=tmp/sum;
    }
    if(!q){
        double tmp=INF;
        for(int i=1;i<=4;i++)
            tmp=min(tmp,dfs(c,d,h,s,p,i));
        res+=tmp/sum;
    }
    return dp[c][d][h][s][p][q]=res+1;
}
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d",&a[1],&a[2],&a[3],&a[4]);
        int tmp=0;
        for(int i=1;i<=4;i++)tmp+=max(0,a[i]-13);
        if(tmp>2){
            printf("Case %d: -1\n",++iCase);
            continue;
        }
        memset(dp,-1,sizeof(dp));
        res=dfs(0,0,0,0,0,0);
        printf("Case %d: %.8lf\n",++iCase,res);
    }
    return 0;
}

在这里插入图片描述

posted @ 2020-03-26 21:03  winechord  阅读(111)  评论(0编辑  收藏  举报