AcWing 218. 扑克牌


\(f[A][B][C][D][X][Y]\)表示当前由A张红桃,B张黑桃,C张梅花,D张方片,且小王的状态为X,大王的状态为Y的情况的期望的最小值
此时可以通过枚举每一个变量的状态得到状态转移

#include 
using namespace std;
const int N = 15;
const double INF = 1e20;
int T, n, A, B, C, D;
double f[N][N][N][N][5][5];
double dp(int a, int b, int c, int d, int x, int y) 
{
    double &v = f[a][b][c][d][x][y];
    if (v >= 0) return v;
    int as = a + (x == 0) + (y == 0);
    int bs = b + (x == 1) + (y == 1);
    int cs = c + (x == 2) + (y == 2);
    int dx = d + (x == 3) + (y == 3);
    if (as >= A && bs >= B && cs >= C && ds >= D)   return v = 0;
    int sum = a + b + c + d + (x != 4) + (y != 4);
    sum = 54 - sum;
    if (sum <= 0)   return v = INF;
    v = 1;
    if (a < 13) v += (13.0 - a) / sum * dp(a + 1, b, c, d, x, y);
    if (b < 13) v += (13.0 - b) / sum * dp(a, b + 1, c, d, x, y);
    if (c < 13) v += (13.0 - c) / sum * dp(a, b, c + 1, d, x, y);
    if (d < 13) v += (13.0 - d) / sum * dp(a, b, c, d + 1, x, y);
    if (x == 4) {
        double t = INF;
        for (int i = 0; i < 4; i ++ )   t = min(t, 1.0 / sum * dp(a, b, c, d, i, y));
        v += t;
    }
    if (y == 4) {
        double t = INF;
        for (int i = 0; i < 4; i ++ )   t = min(t, 1.0 / sum * dp(a, b, c, d, x, i));
        v += t;
    }
    return v;
}
int main() {
    memset(f, -1, sizeof f);
    scanf("%d%d%d%d", &A, &B, &C, &D);
    double t = dp(0, 0, 0, 0, 4, 4);
    if (t > INF / 2)    t = -1;
    printf("%.3lf\n", t);
    return 0;
}