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;
}

浙公网安备 33010602011771号