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

来源:互联网 发布:知乎2016年经济下行 编辑:程序博客网 时间:2024/05/11 18:06

        做过博弈论的题,做过概率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
原创粉丝点击