bzoj 2318 spoj 4060(KPGAME)

来源:互联网 发布:200兆网络限速多少合适 编辑:程序博客网 时间:2024/06/06 04:10

Description



Alice和Bob在玩一个游戏。有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事。取到最后一颗石子的人胜利。Alice在投掷硬币时有p的概率投掷出他想投的一面,同样,Bob有q的概率投掷出他相投的一面。
现在Alice先手投掷硬币,假设他们都想赢得游戏,问你Alice胜利的概率为多少。

Solution



f[i]iAg[i]A
观察到,如果f[i1]>g[i1],A显然是不愿意再取石子的,同样B为了获胜也不愿意取石子。
反之f[i1]<g[i1],双方都想取石子,那么显然的
f[i]=pg[i1]+(1p)g[i]

g[i]=qf[i1]+(1q)f[i]

f[i],g[i]
f[i]=pg[i1]+(1p)qf[i1]1(1p)(1q)

g[i]=qf[i1]+(1q)pg[i1]1(1p)(1q)

搞定~

Code

#include <bits/stdc++.h>using namespace std;typedef long long LL;inline void read(int &t) {    int f = 1;char c;    while (c = getchar(), c < '0' || c > '9') if (c == '-') f = -1;    t = c - '0';    while (c = getchar(), c >= '0' && c <= '9') t = t * 10 + c - '0';    t *= f;}const int N = 1005;double f[N], g[N];int main() {    int T, n;    read(T);    while (T--) {        read(n);        n = min(n, 1000);        double p, q;        scanf("%lf%lf", &p, &q);        f[0] = 0, g[0] = 1;        for (int i = 1; i <= n; ++i) {            if (f[i - 1] > g[i - 1])    p = 1 - p, q = 1 - q;            f[i] = (p * g[i - 1] + (1 - p) * q * f[i - 1]) / (1 - (1 - p) * (1 - q));            g[i] = (q * f[i - 1] + (1 - q) * p * g[i - 1]) / (1 - (1 - p) * (1 - q));            if (f[i - 1] > g[i - 1])    p = 1 - p, q = 1 - q;        }        printf("%.8lf\n", f[n]);    }    return 0;}
0 0
原创粉丝点击