[期望DP] SRM 579 Div1 Hard RockPaperScissors

Solution

E(x)=xAScore(x)×P(x)

只要考慮投了m 輪得到(r,p,s) 的概率和分數就好了。
概率可以這樣DP。
ft,i,r,p,s 表示考慮前t 個骰子,i 沒被丟出來,出了(r,p,s) 的概率。
時間複雜度O(n5)
#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;
        }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章