题意: 从54张牌中抽牌,问抽到a张红,b张黑,c张方,d张梅的概率,当抽取到大王和小王的时候,会固定抽期望步数最少的牌。求最小的期望步数。 思路:期望dp ,dp(a,b,c,d,e,f),a,b,c,d,代表前4种牌的数量,e,f代表大王和小王的状态,要注意判断不合法的情况,即所有牌都抽完了,还是没有得到想要的局面。然后我做的时候理解错题意了,把题意理解炒成期望步数了,其实抽到小王大王的时候选择是固定的,而没有四个分支。
#include<bits/stdc++.h> using namespace std; const double inf=1e20; double dp[16][16][16][16][5][5]; // 54张牌:13张方块 13张梅花 13张 黑桃 13张红桃 1张大王 一张小王 int A,B,C,D; double dfs(int a,int b,int c,int d,int sk,int bk) { if(dp[a][b][c][d][sk][bk]>=0) return dp[a][b][c][d][sk][bk]; int aa=a+(sk==0)+(bk==0); int bb=b+(sk==1)+(bk==1); int cc=c+(sk==2)+(bk==2); int dd=d+(sk==3)+(bk==3); if(aa>=A && bb>=B && cc>=C && dd>=D) return dp[a][b][c][d][sk][bk]=0; if((a+b+c+d+(sk!=4)+(bk!=4))==54) return dp[a][b][c][d][sk][bk]=inf; int al=54-(a+b+c+d+(sk!=4)+(bk!=4)); double res=0; if(a+1<=13) res+=((13-a)*1.0/al *(1+dfs(a+1,b,c,d,sk,bk))); if(b+1<=13) res+=((13-b)*1.0/al*(1+dfs(a,b+1,c,d,sk,bk))); if(c+1<=13) res+=((13-c)*1.0/al*(1+dfs(a,b,c+1,d,sk,bk))); if(d+1<=13) res+=((13-d)*1.0/al*(1+dfs(a,b,c,d+1,sk,bk))); if(sk==4) { double tt=inf; for(int i=0;i<=3;i++) tt=min(tt,dfs(a,b,c,d,i,bk)); res+=1.0/al*(1+tt); } if(bk==4) { double tt=inf; for(int i=0;i<=3;i++) tt=min(tt,dfs(a,b,c,d,sk,i)); res+=1.0/al*(1+tt); } return dp[a][b][c][d][sk][bk]=res; } int main() { int a,b,c,d; cin>>a>>b>>c>>d; A=a,B=b,C=c,D=d; memset(dp,-1,sizeof dp); double tt=dfs(0,0,0,0,4,4); if(tt>inf/2) cout<<"-1.000"<<endl; else printf("%.3lf\n",tt); }