题目链接:http://lightoj.com/volume_showproblem.php?problem=1364
题意:一副牌。依次在桌面上放牌。求放了四种花色的牌为C,D,H,S张时放的牌数的期望。大小王出现时必须将其指定为某种花色。指定时要使最后的期望最小。
思路:DP,记录大小王是不是已经被指定过了。
int c,num=0;
int C,D,H,S;
double f[14][14][14][14][5][5];
double DFS(int c,int d,int h,int s,int x1,int x2)
{
double &ans=f[c][d][h][s][x1][x2];
if(ans>-0.5) return ans;
int q[5];
int tot=c+d+h+s;
if(!x1) tot++;
if(!x2) tot++;
q[1]=13-c;q[2]=13-d;q[3]=13-h;q[4]=13-s;
q[x1]++;q[x2]++;
if(q[1]>=C&&q[2]>=D&&q[3]>=H&&q[4]>=S) return ans=0;
ans=0;
if(c) ans+=1.0*c/tot*DFS(c-1,d,h,s,x1,x2);
if(d) ans+=1.0*d/tot*DFS(c,d-1,h,s,x1,x2);
if(h) ans+=1.0*h/tot*DFS(c,d,h-1,s,x1,x2);
if(s) ans+=1.0*s/tot*DFS(c,d,h,s-1,x1,x2);
int i;
double t;
if(!x1)
{
t=1e20;
FOR1(i,4) t=min(t,DFS(c,d,h,s,i,x2));
ans+=1.0/tot*t;
}
if(!x2)
{
t=1e20;
FOR1(i,4) t=min(t,DFS(c,d,h,s,x1,i));
ans+=1.0/tot*t;
}
ans+=1;
return ans;
}
int main()
{
RD(c);
while(c--)
{
RD(C,D);
RD(H,S);
printf("Case %d: ",++num);
int x=0;
if(C>13) x+=C-13;
if(D>13) x+=D-13;
if(H>13) x+=H-13;
if(S>13) x+=S-13;
if(x>2)
{
puts("-1");
continue;
}
clr(f,-1);
printf("%.8lf\n",DFS(13,13,13,13,0,0));
}
return 0;
}