HDU_5602_概率dp

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

 

dp[1][i][j]表示轮到第二个人操作时,第一人总和i,第二人总和j,第一人胜的最小概率(因为每个人都是聪明的,所以选最小)。

dp[0][i][j]表示第一个人操作时,第一个人胜的最大概率。

先算dp[1],然后用dp[1]算dp[0],注意x==y的情况。

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int vis[2][35][35] = {0};
double dp[2][35][35];
char a[5];

int cal(char c)
{
    switch(c)
    {
        case 'A':   return 1;
        case 'T':
        case 'J':
        case 'K':
        case 'Q':   return 10;
        default:    return c-'0';
    }
}

double dfs1(int x,int y)
{
    if(y > 21)  return 1;
    if(vis[1][x][y])    return dp[1][x][y];
    double temp = 0;
    dp[1][x][y] = x>y;
    for(int i = 1;i < 10;i++)   temp += dfs1(x,y+i)/13;
    temp += dfs1(x,y+10)*4/13;
    dp[1][x][y] = min(dp[1][x][y],temp);
    vis[1][x][y] = 1;
    return dp[1][x][y];
}

double dfs0(int x,int y)
{
    if(x > 21)  return 0;
    if(vis[0][x][y])    return dp[0][x][y];
    dp[0][x][y] = dfs1(x,y);
    double temp = 0;
    for(int i = 1;i < 10;i++)    temp += dfs0(x+i,y)/13;
    temp += dfs0(x+10,y)*4/13;
    dp[0][x][y] = max(dp[0][x][y],temp);
    vis[0][x][y] = 1;
    return dp[0][x][y];
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",a);
        int first = 0,second = 0;
        first += cal(a[0]);
        first += cal(a[1]);
        second += cal(a[2]);
        second += cal(a[3]);
        double ans = dfs0(first,second);
        if(ans > 0.5)   printf("YES\n");
        else    printf("NO\n");
    }
    return 0;
}

 

posted @ 2016-09-21 00:12  zzzzzzzzhu  阅读(255)  评论(1编辑  收藏  举报