100道动态规划——33 HDU 5602 Black Jack 博弈DP?以前没做过这个类型

        做过博弈论的题,做过概率DP的题,可是没有见过这样的题目。。

        要开两个数组进行记忆化搜索。

        其实一部分原因也是因为题目没有描述清楚(误,其实是自己没有看清楚比大小的规则)

        规则是首先是闲家叫牌,不断的叫牌,然后轮到庄家叫牌,不断的叫牌,当庄家不叫牌时,就开始比大小

        不是在电视里看过的那种庄家闲家来回轮流的叫牌。。。。

        在正确理解规则的情况下,整个只有两个回合,一个是闲家叫牌,闲家要让自己的胜率最大,轮到庄家叫牌的时候,庄家会让闲家的胜率最小

        定义状态dp[0][i][j]表示闲家i点,庄家j点,此时是闲家操作的闲家胜率

                       dp[1][i][j]表示闲家i点,庄家j点,此时是庄家操作的庄家胜率

        状态转移方程在代码里面看吧,注意的是在庄家操作的时候假若庄家不叫牌了,就进入了比大小的环节

        博弈DP,其实仔细分析,变化也不是很大,只是换了一个套路而已

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <string>

using namespace std;
const int maxm=35;

inline int p(char c){return (c=='A')?1:((isdigit(c)?c-'0':10));}
bool vis[2][maxm][maxm];
double dp[2][maxm][maxm],dfs0(int a,int b),dfs1(int a,int b);
int times;
string str;

int main(){
    ios_base::sync_with_stdio(false);
    cin>>times;
    while(times--){
        cin>>str;
        cout<<(dfs0(p(str[0])+p(str[1]),p(str[2])+p(str[3]))>0.5?"YES\n":"NO\n");
    }
    return 0;
}

double dfs0(int a, int b){
    if(a>21)
        return 0;
    else if(vis[0][a][b])
        return dp[0][a][b];
    vis[0][a][b]=true;
    dp[0][a][b]=dfs1(a,b);
    double tmp=0;
    for(int i=1;i<10;++i)
        tmp+=dfs0(a+i,b)/13;
    tmp+=dfs0(a+10,b)*4/13;
    return dp[0][a][b]=max(dp[0][a][b],tmp);
}

double dfs1(int a,int b){
    if(b>21)
        return 1;
    else if(vis[1][a][b])
        return dp[1][a][b];
    vis[1][a][b]=true;
    dp[1][a][b]=a>b;
    double tmp=0;
    for(int i=1;i<10;++i)
        tmp+=dfs1(a,b+i)/13;
    tmp+=dfs1(a,b+10)*4/13;
    return dp[1][a][b]=min(tmp,dp[1][a][b]);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值