题意:
Alice和Bob玩起了扑克牌比大小的游戏。首先他们拿来了若干副没有大小王的扑克牌,充分洗牌之后给Alice和Bob各发N张牌,牌的背面朝上,因此两人并不知道这些牌的点数。
之后两人各自从N张牌中随机取出K (K <= N)张,同时翻开并计算各自K张牌的点数之和,谁的点数更大谁就获胜,如果点数相等视作平局。
在扑克牌中,数字牌的点数和牌上的数字相等,A的点数为1,J的点数为11,Q的点数为12,K的点数为13。
现在如果你已经知道了发给Alice和Bob的各是什么样的牌,你能计算出Alice获胜的概率吗?
#include<iostream>
#include<cstring>
#include<iomanip>
using namespace std;
int T,N,K,A[55],B[55],Sum1,Sum2,Hash[150];
double F[55][55][700],Ax[700],Bx[700];
void Init()
{
cout<<fixed<<setprecision(6);
for (char i='2'; i<='9'; i++)
Hash[(int)i]=i-'0';
Hash['A']=1,Hash['X']=10,Hash['J']=11,Hash['Q']=12,Hash['K']=13;
}
int main()
{
Init();
cin>>T;
while (T--)
{
char ch;
cin>>N>>K;
Sum1=Sum2=0;
double C=1;
for (int i=1;i<=K;i++)
C=C*(N-i+1)/i;
for (int i=1; i<=N; i++)
{
cin>>ch;
A[i]=Hash[(int)ch];
Sum1+=A[i];
}
for (int i=1; i<=N; i++)
{
cin>>ch;
B[i]=Hash[(int)ch];
Sum2+=B[i];
}
memset(F,0,sizeof(F));
for (int i=0; i<=N; i++)
F[i][0][0]=1;
for (int i=1; i<=N; i++)
for (int j=1; j<=i&&j<=K; j++)
for (int s=1; s<=Sum1; s++)
if (s>=A[i])
F[i][j][s]=F[i-1][j][s]+F[i-1][j-1][s-A[i]];
else
F[i][j][s]=F[i-1][j][s];
for (int i=1;i<=Sum1;i++)
Ax[i]=1.0*F[N][K][i]/C;
memset(F,0,sizeof(F));
for (int i=0; i<=N; i++)
F[i][0][0]=1;
for (int i=1; i<=N; i++)
for (int j=1; j<=i&&j<=K; j++)
for (int s=1; s<=Sum2; s++)
if (s>=B[i])
F[i][j][s]=F[i-1][j][s]+F[i-1][j-1][s-B[i]];
else
F[i][j][s]=F[i-1][j][s];
Bx[0]=0.0;
for (int i=1;i<=Sum1;i++)
{
Bx[i]=1.0*F[N][K][i]/C;
Bx[i]+=Bx[i-1];
}
double Ans=0;
for (int i=1;i<=Sum1;i++)
Ans+=(double)Ax[i]*Bx[i-1];
cout<<Ans<<endl;
}
return 0;
}