题意:
一副扑克牌,给定四种花色指定数目C,D,H,S,每当大小鬼出现时指定其为一种花色使得抽出最少张数的牌来实现四种花色的牌达到指定数目,求最少张数期望值!(听起来有点艹氮)
解析:
做法嘛,借鉴自某大神博客,是这样子滴~~~~
我们从最初各13张牌加两个鬼牌开始,向最终结果转移,即模拟出每次抽牌的情况,设定四种花色的参数表,依次搜索,最关键的就是鬼牌,我们把它们独立出来,记录他们的情况,是否使用,使用给谁~~搜到 答案状态退出即可,记得最初的几种-1的情况的特判~~
代码、
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int C,D,H,S,t;
int Case,cnt;
int q[5];
double dp[20][20][20][20][5][5];
double f(int c,int d,int h,int s,int x,int y)
{
double ans=dp[c][d][h][s][x][y];
if(ans>0)return ans;
int tot=c+d+h+s+(x==0?1:0)+(y==0?1:0);
q[1]=13-c;q[2]=13-d;q[3]=13-h;q[4]=13-s;
q[x]++;q[y]++;
if(q[1]>=C&&q[2]>=D&&q[3]>=H&&q[4]>=S)return 0;
if(c>0)ans+=1.0*c/tot*f(c-1,d,h,s,x,y);
if(d>0)ans+=1.0*d/tot*f(c,d-1,h,s,x,y);
if(h>0)ans+=1.0*h/tot*f(c,d,h-1,s,x,y);
if(s>0)ans+=1.0*s/tot*f(c,d,h,s-1,x,y);
double t;
if(!x)
{
t=1000000;
for(int i=1;i<=4;i++)
{
t=min(t,f(c,d,h,s,i,y));
}
ans+=1.0/tot*t;
}
if(!y)
{
t=1000000;
for(int i=1;i<=4;i++)
{
t=min(t,f(c,d,h,s,x,i));
}
ans+=1.0/tot*t;
}
ans+=1;
return dp[c][d][h][s][x][y]=ans;
}
int main()
{
scanf("%d",&t);Case=0;
while(t--)
{
scanf("%d%d%d%d",&C,&D,&H,&S);
cnt=0;
if(C>13)cnt+=(C-13);
if(D>13)cnt+=(D-13);
if(H>13)cnt+=(H-13);
if(S>13)cnt+=(S-13);
if(cnt>2){printf("Case %d: -1\n",++Case);continue;}
memset(dp,0,sizeof(dp));
printf("Case %d: %.8lf\n",++Case,f(13,13,13,13,0,0));
}
return 0;
}