hdu5602Black Jack

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5602

题意:给4个字符,字符为"A234566789TJQK"中之一,表示扑克的点数,当然A=1,T=J=Q=K=10。前两个字符是闲家的牌,后两个字符是庄家的牌。玩法是21点的规则(闲家先选择是否加牌--可多张,然后庄家选择是否加牌--可多张),超过21点直接算输,都加完后点数大赢。求最后闲家获胜的概率是否大于0.5,输出YES/NO。

分析:因为出题人说了没种牌的概率为1/13,即不会随着牌少而改变,变得简单了。我们要求的是最后闲家点数是否大于庄家,所以我们可以设状态f[i][j]表示闲家可加牌时闲家获胜的概率,dp[i][j]表示轮到庄家加牌时闲家获胜的概率。很明显我们可以用dfs先求出dp[i][j]整个数组来,而且f[i][j]的求解是依赖于dp[i][j]的,因为闲家拿完牌的边界是庄家开始拿牌即dp[i][j],所以我们同样用dfs处理f[i][j],并且要保证f[i][j]是拿与不拿之间的最大概率。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1000010;
const int MAX=151;
const int MOD=1000007;
const int MOD1=100000007;
const int MOD2=100000009;
const int INF=1000000000;
const double EPS=0.00000001;
typedef long long ll;
typedef unsigned long long ull;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char s[5];
int z[130],bo[22][22],vis[22][22];
double h[22],dp[22][22],f[22][22];
double dfs(int x,int y) {
    if (y>21) return 0;
    if (x<=y) return 1;
    double ret=0;
    for (int i=1;i<=13;i++) ret+=dfs(x,y+min(i,10))/13;
    return ret;
}
double get(int x,int y) {
    if (x>21) return 0;
    if (vis[x][y]) return f[x][y];
    double &ret=f[x][y];
    vis[x][y]=1;ret=0;
    for (int i=1;i<=13;i++) ret+=get(x+min(i,10),y)/13;
    return ret=max(ret,dp[x][y]);
}
void deal() {
    int i,j;
    for (i=1;i<22;i++)
        for (j=1;j<22;j++) dp[i][j]=1-dfs(i,j);
    memset(vis,0,sizeof(vis));
    for (i=1;i<22;i++)
        for (j=1;j<22;j++)
        if (get(i,j)>0.5) bo[i][j]=1;
        else bo[i][j]=0;
}
int main()
{
    int i,t,x,y;
    z['A']=1;z['2']=2;z['3']=3;z['4']=4;z['5']=5;
    z['6']=6;z['7']=7;z['8']=8;z['9']=9;z['T']=10;
    z['J']=10;z['Q']=10;z['K']=10;
    deal();
    scanf("%d", &t);
    while (t--) {
        scanf("%s", s);
        x=z[s[0]]+z[s[1]];y=z[s[2]]+z[s[3]];
        if (bo[x][y]) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值