PassTheBuck (概率)

题目连接

题意:

进行一个游戏,有几个参与者,每个参与者在其他参与者之间有一个或多个邻居。

每场比赛开始时,随机选出一名玩家,他将获得一美元(当前的持有者)。(在这个游戏中,随机选择意味着每种可能的结果都有相同的概率。)

然后,在每一步,如果当前持有者有d个邻居,他/她在[0,d]范围内随机选择一个整数k。如果选择0,当前持有者就是赢家,持有美元。否则,持有者将把美元传递给指数为k的邻居,成为新的持有者。

游戏继续进行,直到有一方获胜。

玩家和邻居的配置可以建模为一个以玩家为顶点的图,如果对应的玩家是邻居,则两个顶点之间有一条边。例如,如果他们坐在一排,那么左邻右邻就是玩家(如果有的话)。

有q组询问,求从玩家 i 开始,玩家 j 获胜的概率。

思路:

可以由当前到达各个玩家的概率,求出下一步到达所有玩家的概率,当获胜的概率比较小时退出循环,得到答案。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define sll(a) scanf("%lld", &a)
 5 #define sll2(a, b) scanf("%lld %lld", &a, &b)
 6 #define int long long
 7 
 8 const int maxn = 1e5 + 10;
 9 const int mod = 1e9 + 7;
10 
11 const double esp=1e-8;
12 int G[50][50],n,d[50];
13 double solve(int u,int v)
14 {
15     double now[25],nex[25],ans=0,num=0;
16     for(int i=0;i<21;i++) now[i]=nex[i]=0.0;
17     now[u]=1;
18     while(num==0.0||num>esp)
19     {
20         ans+=num;
21         num=0.0;
22         for(int i=0;i<=n;i++)nex[i]=0;
23         for(int i=1;i<=n;i++)
24         {
25             if(now[i]>0.0)
26                 for(int j=1;j<=n;j++)
27                 {
28                     if(G[i][j])
29                     {
30                         if(i==j)
31                         {if(i==v)num+=now[i]*1.0/d[i];}
32                         else
33                             nex[j]+=now[i]*1.0/d[i];
34                     }
35                 }
36         }
37         for(int i=1;i<=n;i++)
38             now[i]=nex[i];
39     }
40     return ans;
41 }
42 signed main()
43 {
44     int m;
45     sll2(n,m);
46     for(int i=1;i<=n;i++)
47     {
48         int x;
49         sll(x);d[i]=x+1;
50         while(x--){int a;sll(a);G[i][a]=1,G[a][i]=1;}
51         G[i][i]=1;
52     }
53     while (m--)
54     {
55         int t,u,v;
56         sll(t);sll2(u,v);
57         printf("%lld %.5f\n",t,solve(u,v));
58     }
59     return 0;
60 }

 


posted @ 2020-10-12 17:11  一个只会爆零的小菜鸡  阅读(170)  评论(0编辑  收藏  举报