acwing218扑克牌

题目描述

Admin生日那天,Rainbow来找Admin玩扑克牌。
玩着玩着Rainbow觉得太没意思了,于是决定给Admin一个考验。
Rainbow把一副扑克牌(54 张)随机洗开,倒扣着放成一摞。
然后Admin 从上往下依次翻开每张牌,每翻开一张黑桃、红桃、梅花或者方块,就把它放到对应花色的堆里去。
Rainbow想问问Admin,得到A张黑桃,B张红桃,C张梅花,D张方块需要翻开的牌的张数的期望值E是多少?
特殊地,如果翻开的牌是大王或者小王,Admin将会把它作为某种花色的牌放入对应堆中,使得放入之后E的值尽可能小。
由于Admin和Rainbow还在玩扑克,所以这个程序就交给你来写了。

输入格式

输入仅由一行,包含四个用空格隔开的整数,A,B,C,D。

输出格式

输出需要翻开的牌数的期望值E,四舍五入保留3位小数。如果不可能达到输入的状态,输出-1.000。

样例

输入

1 2 3 4

输出

16.393
数据范围0<=A,B,C,D<=15

#include<bits/stdc++.h>
using namespace std;

const int inf=0x3f3f3f3f;
double f[15][15][15][15][5][5];
int A,B,C,D;//A黑桃 B红桃 C梅花 D方片要求数量 

//如果翻出大小王x=1放a...... 
void add(int &a,int &b,int &c,int &d,int x){
	if(x==1) a++;
	if(x==2) b++;
	if(x==3) c++;
	if(x==4) d++;
}
//0是未翻出1,2,3,4表示四种花色 
double dfs(int a,int b,int c,int d,int x,int y){//依次代表四种花色小大王 
	if(f[a][b][c][d][x][y]>0) return f[a][b][c][d][x][y];
	int ta=a,tb=b,tc=c,td=d;
	add(ta,tb,tc,td,x);
	add(ta,tb,tc,td,y);
	if(ta>=A&&tb>=B&&tc>=C&&td>=D) return 0;//所有的都达到目标期望值才为0 
	int rst=54-ta-tb-tc-td;//剩下的牌的数量 
	if(rst<=0) return inf;//没有牌了还没达到目标 
	double v=1;
	if(a<13)//有概率翻出概率为花色数量/剩下的总数量 
		v+=dfs(a+1,b,c,d,x,y)*(13-a)/rst;
	if(b<13)
		v+=dfs(a,b+1,c,d,x,y)*(13-b)/rst;
	if(c<13)
		v+=dfs(a,b,c+1,d,x,y)*(13-c)/rst;
	if(d<13)
		v+=dfs(a,b,c,d+1,x,y)*(13-d)/rst;
	if(x==0)//取E值最小的一个 
		v+=min({dfs(a,b,c,d,1,y),dfs(a,b,c,d,2,y),dfs(a,b,c,d,3,y),dfs(a,b,c,d,4,y)})/rst;
	if(y==0)
		v+=min({dfs(a,b,c,d,x,1),dfs(a,b,c,d,x,2),dfs(a,b,c,d,x,3),dfs(a,b,c,d,x,4)})/rst;
	return f[a][b][c][d][x][y]=v;//本状态的期望值 
}

int main(){
	scanf("%d%d%d%d",&A,&B,&C,&D);
	double ans=dfs(0,0,0,0,0,0);
	if(res>inf/2) printf("-1.000");
	else printf("%.3lf",ans);
	
	return 0;
}

借鉴于

posted @ 2024-05-29 10:54  晨曦ccx  阅读(28)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end