LightOJ - 1364 Expected Cards(概率dp)

题目链接:Expected Cards - LightOJ 1364 - Virtual Judge (ppsucxtt.cn)

题意:Taha 把一副扑克牌(54张)随机洗开,倒扣着放成一摞。然后从上往下依次翻开每张牌,每翻开一张黑桃、红桃、梅花或者方块,就把它放到对应花色的堆里去。Taha想知道得到 A 张黑桃、B 张红桃、C 张梅花、D 张方块需要翻开的牌的张数的期望值 E 是多少?特殊地,如果翻开的牌是大王或者小王,Taha 将会把它作为某种花色的牌放入对应堆中,使得放入之后 E 的值尽可能小。

我之前做过一道基本上一模一样的题目,那道题目是单组输入,而这道题目是多组输入,只要记得初始化数组就好,下面附上我之前写的那道题的博客地址:(59条消息) (ACW218)扑克牌(数学期望)_AC__dream的博客-CSDN博客

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=16;
double f[N][N][N][N][5][5];
int A,B,C,D;
double dp(int a,int b,int c,int d,int E,int F)
{
	if(f[a][b][c][d][E][F]) return f[a][b][c][d][E][F];
	int cnta=a+(E==1)+(F==1);
	int cntb=b+(E==2)+(F==2);
	int cntc=c+(E==3)+(F==3);
	int cntd=d+(E==4)+(F==4);
	if(cnta>=A&&cntb>=B&&cntc>=C&&cntd>=D) return 0;
	double ans=1;
	int cnt=cnta+cntb+cntc+cntd;
	if(a<13) ans+=1.0*(13-a)/(54-cnt)*dp(a+1,b,c,d,E,F);
	if(b<13) ans+=1.0*(13-b)/(54-cnt)*dp(a,b+1,c,d,E,F);
	if(c<13) ans+=1.0*(13-c)/(54-cnt)*dp(a,b,c+1,d,E,F);
	if(d<13) ans+=1.0*(13-d)/(54-cnt)*dp(a,b,c,d+1,E,F);
	if(E==0)
	{
		double t=9999999999;
		for(int i=1;i<=4;i++)
			t=min(t,dp(a,b,c,d,i,F)/(54-cnt));
		ans+=t;
	}
	if(F==0)
	{
		double t=9999999999;
		for(int i=1;i<=4;i++)
			t=min(t,dp(a,b,c,d,E,i)/(54-cnt));
		ans+=t;
	}
	return f[a][b][c][d][E][F]=ans;
}
int main()
{
	int T;
	cin>>T;
	for(int o=1;o<=T;o++)
	{
		int n;
		cin>>A>>B>>C>>D;
		int t=0;
		memset(f,0,sizeof f);
		if(A>13) t+=A-13;
		if(B>13) t+=B-13; 
		if(C>13) t+=C-13; 
		if(D>13) t+=D-13; 
		if(t>2)	printf("Case %d: -1\n",o);
		else printf("Case %d: %.10lf\n",o,dp(0,0,0,0,0,0));
	}
	return 0;
}

上一篇:概率专题一(LightOJ - 1027 LightOJ - 1030 LightOJ - 1038 LightOJ - 1079)


下一篇:Github提交Spark代码