[期望DP] SRM 579 Div1 Hard RockPaperScissors

Solution S o l u t i o n

E(x)=xAScore(x)×P(x) E ( x ) = ∑ x ∈ A S c o r e ( x ) × P ( x )

只要考虑投了 m m 轮得到(r,p,s)的概率和分数就好了。
概率可以这样DP。
ft,i,r,p,s f t , i , r , p , s 表示考虑前 t t 个骰子,i没被丢出来,出了 (r,p,s) ( r , p , s ) 的概率。
时间复杂度 O(n5) O ( n 5 )

#define show(x) cerr << #x << " = " << x << endl
using namespace std;
typedef long long ll;
typedef pair<int, int> Pairs;

const int N = 51;

inline char get(void) {
    static char buf[100000], *S = buf, *T = buf;
    if (S == T) {
        T = (S = buf) + fread(buf, 1, 100000, stdin);
        if (S == T) return EOF;
    }
    return *S++;
}
template<typename T>
inline void read(T &x) {
    static char c; x = 0; int sgn = 0;
    for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
    for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
    if (sgn) x = -x;
}

int n;
int a[N], b[N], c[N];
double q[N][4];
double f[N][N][N][N];
double ans;

class RockPaperScissors {
    public:
        double bestScore(vector <int> Pr, vector <int> Pp, vector <int> Ps) {
            n = Pr.size();
            for (int i = 1; i <= n; i++) {
                q[i][1] = (double)Pr[i - 1] / 300;
                q[i][2] = (double)Pp[i - 1] / 300;
                q[i][3] = (double)Ps[i - 1] / 300;
            }
            for (int i = 1; i <= n; i++) f[i][0][0][0] = 1;
            for (int t = 1; t <= n; t++) {
                for (int m = t; m >= 0; m--)
                    for (int r = 0; r <= m; r++)
                        for (int p = 0; p + r <= m; p++) {
                            int s = m - r - p;
                            double prob = (double)m / t;
                            for (int i = 1; i <= n; i++) {
                                f[i][r][p][s] *= (1 - prob);
                                if (i == t) continue;
                                if (r > 0) f[i][r][p][s] += f[i][r - 1][p][s] * prob * q[t][1];
                                if (p > 0) f[i][r][p][s] += f[i][r][p - 1][s] * prob * q[t][2];
                                if (s > 0) f[i][r][p][s] += f[i][r][p][s - 1] * prob * q[t][3];
                            }
                        }
            }
            for (int r = 0; r < n; r++)
                for (int p = 0; p + r < n; p++)
                    for (int s = 0; s + p + r < n; s++) {
                        int m = r + p + s;
                        double pr = 0, pq = 0, ps = 0;
                        for (int i = 1; i <= n; i++) {
                            double cur = f[i][r][p][s];
                            pr += cur * q[i][1];
                            pq += cur * q[i][2];
                            ps += cur * q[i][3];
                        }
                        pr /= (n - m); pq /= (n - m); ps /= (n - m);
                        ans += max(max(pr + ps * 3, pq + pr * 3), ps + pq * 3);
                    }
            return ans;
        }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值