TYVJ2002 扑克牌(期望)

博客介绍了如何计算扑克牌游戏中,根据已翻牌的花色和王的状态,求剩余牌的期望值。通过定义状态转移数组dp,博主解析了递推公式,并说明了在特定情况下如何选择最优策略。最后提到了使用记忆化搜索来优化算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

【题目分析】

定义数组dp[a][b][c][d][x][y]表示当前已经翻了a张黑桃,b张红桃,c张梅花,d张方块,小王状态为x,大王状态为y的期望值,x,y为0-4的数,分别表示黑桃红桃梅花方块和未翻。

那么现在剩下的牌就是res=(54-a-b-c-d-(x!=4)-(y!=4))

那么我们可以得到dp[a][b][c][d][x][y]的递推式:

dp[a][b][c][d][x][y]=dp[a+1][b][c][d][x][y]*\frac{13-a-(x==0)-(y==0))}{res}+dp[a][b+1][c][d][x][y]*\frac{13-b-(x==1)-(y==1))}{res}+dp[a][b][c+1][d][x][y]*\frac{13-c-(x==2)-(y==2))}{res}+dp[a][b][c][d+1][x][y]*\frac{13-d-(x==3)-(y==3))}{res}

如果x=4或y=4,那么此时要讨论1/res的概率选到小王或者大王,因为最后要最优,所以一定是在所有花色中选最小值。枚举花色继续枚举即可。因为概率和一定为1,所以对于每个状态的期望加上一个1即可。

然后再记忆化一下就行了。

【代码~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=20;

int A,B,C,D;
int vis[MAXN][MAXN][MAXN][MAXN][5][5];
double dp[MAXN][MAXN][MAXN][MAXN][5][5],ans;

double solve(int a,int b,int c,int d,int x,int y){
	if(vis[a][b][c][d][x][y])
	  return dp[a][b][c][d][x][y];
	vis[a][b][c][d][x][y]=1;
	double ret=0.0;
	int na=a+(x==0)+(y==0),nb=b+(x==1)+(y==1),nc=c+(x==2)+(y==2),nd=d+(x==3)+(y==3);
	if(na>=A&&nb>=B&&nc>=C&&nd>=D)
	  return dp[a][b][c][d][x][y]=0;
	double res=54.0-a-b-c-d-(x!=4)-(y!=4);
	if(res<0)
	  return 100.0;
	if(a<13)
	  ret+=solve(a+1,b,c,d,x,y)*(1.0*(13-a))/res;
	if(b<13)
	  ret+=solve(a,b+1,c,d,x,y)*(1.0*(13-b))/res;
	if(c<13)
	  ret+=solve(a,b,c+1,d,x,y)*(1.0*(13-c))/res;
	if(d<13)
	  ret+=solve(a,b,c,d+1,x,y)*(1.0*(13-d))/res;
	if(x==4){
		double s=min(solve(a,b,c,d,0,y),min(solve(a,b,c,d,1,y),min(solve(a,b,c,d,2,y),solve(a,b,c,d,3,y))));
		ret+=s/res;
	}
	if(y==4){
		double s=min(solve(a,b,c,d,x,0),min(solve(a,b,c,d,x,1),min(solve(a,b,c,d,x,2),solve(a,b,c,d,x,3))));
		ret+=s/res;
	}
	return dp[a][b][c][d][x][y]=ret+1.0;
}

int main(){
	cin>>A>>B>>C>>D;
	ans=solve(0,0,0,0,4,4);
	if(ans>54)
	  puts("-1.000");
	else
	  printf("%.3lf",ans);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值