题意 : 有54张牌 问抽多少张牌能使每种花色都至少是给定的数字 两张王牌可以被选择为任何花色
高放学长真是太腻害辣!
设置dp[][][][][x][y] 前四维代表四种真的花色的数量 后两维xy代表大王与小王的使用情况——是没有用到 还是作为1234
于是dp[i][j][k][l][x][y]当x为0时 可以来自于dp[i][j][k][l][1][y] dp....[2][y]....
期望倒推 所以 当前的四种状态都已经算出来了 选一个最小的 即“选一个最小的期望转变” // 事实上我们已经知道四种分支各自还需要抽牌的期望了
当ijkl<13时 还可能来自于dp[i+1][k][j][l][x][y] 即正常抽牌
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #include<map> #include<iostream> #include<string> #include<vector> #include<queue> using namespace std; #define L long long double dp[16][16][16][16][5][5] ; bool f[16][16][16][16][5][5] ; int a,b,c,d; int main(){ int t; scanf("%d",&t); int cas = 1 ; while(t--) { scanf("%d%d%d%d",&a,&b,&c,&d) ; int jz=0; if(a>13)jz+=(a-13); if(b>13)jz+=(b-13); if(c>13)jz+=(c-13); if(d>13)jz+=(d-13); if(jz>2){ printf("Case %d: -1.000 ",cas++); continue; } memset(dp,0,sizeof(dp)); memset(f,false,sizeof(f)); for(int i=13;i>=0;i--){ for(int j=13;j>=0;j--){ for(int k=13;k>=0;k--){ for(int l=13;l>=0;l--){ for(int x=4;x>=0;x--){ for(int y=4;y>=0;y--){ int aa=i,bb=j,cc=k,dd=l; if(x==1)aa++; else if(x==2)bb++; else if(x==3)cc++; else if(x==4)dd++; if(y==1)aa++; else if(y==2)bb++; else if(y==3)cc++; else if(y==4)dd++; if(aa>=a&&bb>=b&&cc>=c&&dd>=d){ } else { f[i][j][k][l][x][y] = true ; } } } } } } } for(int i=13;i>=0;i--){ for(int j=13;j>=0;j--){ for(int k=13;k>=0;k--){ for(int l=13;l>=0;l--){ for(int x=4;x>=0;x--){ for(int y=4;y>=0;y--){ int aa=i,bb=j,cc=k,dd=l; if(x==1)aa++; else if(x==2)bb++; else if(x==3)cc++; else if(x==4)dd++; if(y==1)aa++; else if(y==2)bb++; else if(y==3)cc++; else if(y==4)dd++; if(f[i][j][k][l][x][y]==true){ f[i][j][k][l][x][y]=false; int sum=54-aa-bb-cc-dd; int s=0; if(x!=0)s++; if(y!=0)s++; dp[i][j][k][l][x][y] = 1.0 ; if(x==0){ double u = min(min(dp[i][j][k][l][1][y],dp[i][j][k][l][2][y]),min(dp[i][j][k][l][3][y],dp[i][j][k][l][4][y])) ; dp[i][j][k][l][x][y] += u * 1.0/sum ; } if(y==0){ double u = min(min(dp[i][j][k][l][x][1],dp[i][j][k][l][x][2]),min(dp[i][j][k][l][x][3],dp[i][j][k][l][x][4])) ; dp[i][j][k][l][x][y] += u * 1.0/sum ; } if(i<13)dp[i][j][k][l][x][y] += dp[i+1][j][k][l][x][y] * (13-i)*1.0/sum ; if(j<13)dp[i][j][k][l][x][y] += dp[i][j+1][k][l][x][y] * (13-j)*1.0/sum ; if(k<13)dp[i][j][k][l][x][y] += dp[i][j][k+1][l][x][y] * (13-k)*1.0/sum ; if(l<13)dp[i][j][k][l][x][y] += dp[i][j][k][l+1][x][y] * (13-l)*1.0/sum ; } } } } } } } printf("Case %d: %.3f ",cas++,dp[0][0][0][0][0][0]); } }