UvaLive 5811 概率DP

题意 : 有54张牌 问抽多少张牌能使每种花色都至少是给定的数字 两张王牌可以被选择为任何花色

高放学长真是太腻害辣!

设置dp[][][][][x][y] 前四维代表四种真的花色的数量 后两维xy代表大王与小王的使用情况——是没有用到 还是作为1234

于是dp[i][j][k][l][x][y]当x为0时 可以来自于dp[i][j][k][l][1][y] dp....[2][y]....

期望倒推 所以 当前的四种状态都已经算出来了 选一个最小的 即“选一个最小的期望转变” // 事实上我们已经知道四种分支各自还需要抽牌的期望了

当ijkl<13时 还可能来自于dp[i+1][k][j][l][x][y] 即正常抽牌

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<iostream>
#include<string>
#include<vector>
#include<queue>
using namespace std;
#define L long long

double dp[16][16][16][16][5][5] ;
bool f[16][16][16][16][5][5] ;
int a,b,c,d;

int main(){
    int t;
    scanf("%d",&t);
    int cas = 1 ;
    while(t--) {
        scanf("%d%d%d%d",&a,&b,&c,&d) ;
        int jz=0;
        if(a>13)jz+=(a-13);
        if(b>13)jz+=(b-13);
        if(c>13)jz+=(c-13);
        if(d>13)jz+=(d-13);
        if(jz>2){
            printf("Case %d: -1.000
",cas++);
            continue;
        }
        memset(dp,0,sizeof(dp));
        memset(f,false,sizeof(f));
        for(int i=13;i>=0;i--){
            for(int j=13;j>=0;j--){
                for(int k=13;k>=0;k--){
                    for(int l=13;l>=0;l--){
                        for(int x=4;x>=0;x--){
                            for(int y=4;y>=0;y--){
                                int aa=i,bb=j,cc=k,dd=l;
                                if(x==1)aa++;
                                else if(x==2)bb++;
                                else if(x==3)cc++;
                                else if(x==4)dd++;
                                if(y==1)aa++;
                                else if(y==2)bb++;
                                else if(y==3)cc++;
                                else if(y==4)dd++;
                                if(aa>=a&&bb>=b&&cc>=c&&dd>=d){

                                }
                                else {
                                    f[i][j][k][l][x][y] = true ;
                                }
                            }
                        }
                    }
                }
            }
        }
        for(int i=13;i>=0;i--){
            for(int j=13;j>=0;j--){
                for(int k=13;k>=0;k--){
                    for(int l=13;l>=0;l--){
                        for(int x=4;x>=0;x--){
                            for(int y=4;y>=0;y--){
                                int aa=i,bb=j,cc=k,dd=l;
                                if(x==1)aa++;
                                else if(x==2)bb++;
                                else if(x==3)cc++;
                                else if(x==4)dd++;
                                if(y==1)aa++;
                                else if(y==2)bb++;
                                else if(y==3)cc++;
                                else if(y==4)dd++;
                                if(f[i][j][k][l][x][y]==true){
                                    f[i][j][k][l][x][y]=false;
                                    int sum=54-aa-bb-cc-dd;
                                    int s=0;
                                    if(x!=0)s++;
                                    if(y!=0)s++;
                                    dp[i][j][k][l][x][y] = 1.0 ;
                                    if(x==0){
                                        double u = min(min(dp[i][j][k][l][1][y],dp[i][j][k][l][2][y]),min(dp[i][j][k][l][3][y],dp[i][j][k][l][4][y])) ;
                                        dp[i][j][k][l][x][y] += u * 1.0/sum ;
                                    }
                                    if(y==0){
                                        double u = min(min(dp[i][j][k][l][x][1],dp[i][j][k][l][x][2]),min(dp[i][j][k][l][x][3],dp[i][j][k][l][x][4])) ;
                                        dp[i][j][k][l][x][y] += u * 1.0/sum ;
                                    }
                                    if(i<13)dp[i][j][k][l][x][y] += dp[i+1][j][k][l][x][y] * (13-i)*1.0/sum ;
                                    if(j<13)dp[i][j][k][l][x][y] += dp[i][j+1][k][l][x][y] * (13-j)*1.0/sum ;
                                    if(k<13)dp[i][j][k][l][x][y] += dp[i][j][k+1][l][x][y] * (13-k)*1.0/sum ;
                                    if(l<13)dp[i][j][k][l][x][y] += dp[i][j][k][l+1][x][y] * (13-l)*1.0/sum ;
                                }
                            }
                        }
                    }
                }
            }
        }
        printf("Case %d: %.3f
",cas++,dp[0][0][0][0][0][0]);
    }
}

  

原文地址:https://www.cnblogs.com/rayrayrainrain/p/6566585.html