码迷,mamicode.com
首页 > 其他好文 > 详细

传球游戏

时间:2018-02-24 19:35:51      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:post   保留   play   str   game   sample   通过   表示   code   

Description

\(\mathrm{y}\) 痴迷于玩游戏。

班队课上文艺委员小 \(\mathrm{y}\) 组织大家坐成一圈玩传球游戏,每个人都可以把球向左或者向右传。当然每个同学对于自己左右的伙伴喜爱程度可能不一样,所以拿到球之后往两边传的概率也不一样。最后一个被传到球的人被认为是胜利者。作为游戏的组织者,小 \(\mathrm{y}\) 想知道选定自己的某个死党作为游戏的开始者时,自己的胜率是多少。

Input

输入文件 \(\mathrm{solve.in}\) 包含多组数据。

第一行包含一个整数 ,表示数据组数。

每组数据第一行包含两个整数 \(N,K\) ,表示游戏人数(小 \(\mathrm{y}\) 位置为 \(N\) )以及小 \(y\) 死党的位置。接下来是 \(N\) 行,每行包含一个实数 \(P_i\) ,表示第 \(i\) 个人传球给自己右边概率(小 \(\mathrm{y}\) 组织大家按编号逆时针坐成一圈)。

Output

输出文件为 \(\mathrm{game.out}\)

对于每组数据,输出小 \(y\) 的胜率,保留 \(9\) 位小数。

Sample

Sample Input

1
5 1
0.10
0.20
0.30
0.40
0.50

Sample Output

0.007692308

Limit

\(20\%\) 的数据满足 \(N\le 3\)

\(70\%\) 的数据满足 \(T,N\le 100\)

\(100\%\) 的数据满足 \(T\le 10000,1<N\le 100\)

Solution

先摘抄一段题解。 考虑相邻的三个人 \(a,b,c\) ,假设球一开始在 \(a\) 手上,在球传到 \(a\) 的左边之前 \(a\) 通过 \(b\) 把球传给 \(c\) 的概率设为 \(x\) ;假设球在 \(b\) ,球传到 \(a\) 的左边之前传给 \(c\) 的概率为 \(y\) ,那么有 \[\begin{cases} x=p[a]\times y \\ y=p[b]+(1-p[b])\times x \end{cases}\] 于是我们可以解出 \(x\) 。同理可以解出球从 \(c\) 的手上不经过其他人传到 \(a\) 的概率。

这样一来我们就可以用这两个概率替换 \(a\) 往右传的概率和 \(c\) 往左传的概率,相当于把 \(b\) 删除。

不断删除点,直至最后剩下 \(1,n,n-1,k\) ,然后把 \(k\) 删除,答案就变成了 \[(1-p[K]) \times p[1] + p[K] \times (1-p[n - 1])\]

然后再特判一下 \(K=n-1\)\(K=1\) 的情况就好了。

注意此题要使用 \(\mathrm{long \ double}\)

#include<bits/stdc++.h>
using namespace std;
#define N 101
#define rep(i, a, b) for (int i = a; i <= b; i++)

int n, K;
long double dp[N][N], p[N], q[N];
double t;
int pre[N], nxt[N];

inline void del(int b) {
    int a = pre[b], c = nxt[b];
    long double pa = p[a], pb = p[b], pc = p[c];
    p[a] = pa * pb / (1 - pa * (1 - pb)), q[a] = 1 - p[a];
    q[c] = (1 - pc) * (1 - pb) / (1 - pb * (1 - pc)), p[c] = 1 - q[c];
    nxt[a] = c, pre[c] = a;
}

inline long double solve() {
    if(n <= 2) return 1;
    if(n == 3)return K == 1 ? p[1] : q[2];
    rep(i, 1, n) pre[i] = i - 1, nxt[i] = i + 1; pre[1] = n, nxt[n] = 1;
    if(K == 1) { rep(i, 2, n - 2) del(i); return p[1]; }
    if(K == n - 1) { rep(i, 2, n - 2) del(i); return q[n - 1]; }
    rep(i, 2, K - 1) del(i);
    rep(i, K + 1, n - 2) del(i);
    del(K);
    return q[K] * p[1] + p[K] * q[n - 1];
}

int main() {
    freopen("game.in", "r", stdin); freopen("game.out", "w", stdout);
    int T; cin >> T;
    while(T--) {
        scanf("%d%d", &n, &K);
        rep(i, 1, n) scanf("%lf", &t), p[i] = t, q[i] = 1 - t;
        printf("%.9lf\n", (double)solve());
    }
    return 0;
}

传球游戏

标签:post   保留   play   str   game   sample   通过   表示   code   

原文地址:https://www.cnblogs.com/aziint/p/8467279.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!