题目自己看吧,不想赘述。
参考链接:http://www.cnblogs.com/jianglangcaijin/archive/2013/01/02/2842389.html

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> /* dp[c][d][h][s][x1][x2]: 表示有c张为梅花,d张为方块,h张为红桃,s张为草花,第一张王作为x1,第二张作为x2 的情况下, 距离目标状态的期望数。 */ using namespace std; const int INF=0x3f3f3f3f; double dp[14][14][14][14][5][5]; int vis[14][14][14][14][5][5]; int C,D,H,S; double dfs(int c,int d,int h,int s,int x1,int x2){ if(vis[c][d][h][s][x1][x2]) return dp[c][d][h][s][x1][x2]; vis[c][d][h][s][x1][x2]=1; int left=52-c-d-h-s; //剩余的牌数 if(!x1) left++; if(!x2) left++; int cnt[5]; //现有花色的牌数 cnt[1]=c;cnt[2]=d;cnt[3]=h;cnt[4]=s; if(x1) cnt[x1]++; if(x2) cnt[x2]++; if(cnt[1]>=C&&cnt[2]>=D&&cnt[3]>=H&&cnt[4]>=S) return 0; double ans=0; int num[5]; //储存各花色剩余的牌数 num[1]=13-c; num[2]=13-d; num[3]=13-h; num[4]=13-s; //当前抽中c的概率为num[1]/left,下面类同 if(num[1]) ans+=1.0*num[1]/left*dfs(c+1,d,h,s,x1,x2); if(num[2]) ans+=1.0*num[2]/left*dfs(c,d+1,h,s,x1,x2); if(num[3]) ans+=1.0*num[3]/left*dfs(c,d,h+1,s,x1,x2); if(num[4]) ans+=1.0*num[4]/left*dfs(c,d,h,s+1,x1,x2); double tmp=INF; if(!x1){ for(int i=1;i<=4;i++){ tmp=min(tmp,dfs(c,d,h,s,i,x2)); } ans+=1.0/left*tmp; } tmp=INF; if(!x2){ for(int i=1;i<=4;i++){ tmp=min(tmp,dfs(c,d,h,s,x1,i)); } ans+=1.0/left*tmp; } ans++; //加1,即必须抽1张牌 dp[c][d][h][s][x1][x2]=ans; return ans; } int main() { int t,cases=0; scanf("%d",&t); while(t--){ scanf("%d%d%d%d",&C,&D,&H,&S); 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){ printf("Case %d: -1 ",++cases); continue; } memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); printf("Case %d: %.7lf ",++cases,dfs(0,0,0,0,0,0)); } return 0; }