#概率和数学期望,动态规划,记忆化搜索#CH 3803 扑克牌
分析
首先很容易发现这是一道动态规划的题目,然后设表示,那么,答案是,当翻开的牌达到已知量边界为0
代码
#include <cstdio>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
double f[15][15][15][15][5][5],ans; int t1,t2,t3,t4;
double dp(int a,int b,int c,int d,int p,int q){
if (f[a][b][c][d][p][q]) return f[a][b][c][d][p][q];//记忆化搜索
rr double &ans=f[a][b][c][d][p][q]; ans=0;
rr int x1=a,x2=b,x3=c,x4=d;
if (p==1) ++x1; if (p==2) ++x2; if (p==3) ++x3; if (p==4) ++x4;
if (q==1) ++x1; if (q==2) ++x2; if (q==3) ++x3; if (q==4) ++x4;
if (x1>=t1&&x2>=t2&&x3>=t3&&x4>=t4) return 0;//达到目标
rr int cnt=54-x1-x2-x3-x4;
if (cnt<=0) return ans=1e10;//不可能的状态
if (a<13) ans+=dp(a+1,b,c,d,p,q)*(13-a)/cnt;
if (b<13) ans+=dp(a,b+1,c,d,p,q)*(13-b)/cnt;
if (c<13) ans+=dp(a,b,c+1,d,p,q)*(13-c)/cnt;
if (d<13) ans+=dp(a,b,c,d+1,p,q)*(13-d)/cnt;
if (!p){
double t=dp(a,b,c,d,1,q);
t=min(t,dp(a,b,c,d,2,q));
t=min(t,dp(a,b,c,d,3,q));
t=min(t,dp(a,b,c,d,4,q));
ans+=t/cnt;
}
if (!q){
double t=dp(a,b,c,d,p,1);
t=min(t,dp(a,b,c,d,p,2));
t=min(t,dp(a,b,c,d,p,3));
t=min(t,dp(a,b,c,d,p,4));
ans+=t/cnt;
}
return ++ans;
}
signed main(){
scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
ans=dp(0,0,0,0,0,0);
if (ans>=1e10) ans=-1;
printf("%.3lf",ans);
}