zoukankan      html  css  js  c++  java
  • bzoj 3191: [JLOI2013]卡牌游戏

    Description

    N个人坐成一圈玩游戏。一开始我们把所有玩家按顺时针从1到N编号。首先第一回合是玩家1作为庄家。每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把卡片上的数字向所有玩家展示,然后按顺时针从庄家位置数第X个人将被处决即退出游戏。然后卡片将会被放回卡牌堆里并重新洗牌。被处决的人按顺时针的下一个人将会作为下一轮的庄家。那么经过N-1轮后最后只会剩下一个人,即为本次游戏的胜者。现在你预先知道了总共有M张卡片,也知道每张卡片上的数字。现在你需要确定每个玩家胜出的概率。
    这里有一个简单的例子:
    例如一共有4个玩家,有四张卡片分别写着3,4,5,6.
    第一回合,庄家是玩家1,假设他选择了一张写着数字5的卡片。那么按顺时针数1,2,3,4,1,最后玩家1被踢出游戏。
    第二回合,庄家就是玩家1的下一个人,即玩家2.假设玩家2这次选择了一张数字6,那么2,3,4,2,3,4,玩家4被踢出游戏。
    第三回合,玩家2再一次成为庄家。如果这一次玩家2再次选了6,则玩家3被踢出游戏,最后的胜者就是玩家2.

    Solution

    (f[i][j]) 表示(i)个人玩游戏,获胜的人的为(j)的概率,其中(1)为庄家
    枚举选择的卡 (a[k]),算出被处决的人的位置(t)
    我们只需要讨论删除这个人之后 (j) ,庄家变为(i+1)后,这个人在上一轮中的编号,转移即可

    #include<bits/stdc++.h>
    using namespace std;
    const int N=55;
    double f[N][N];int n,m,a[N];
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      scanf("%d%d",&n,&m);
      for(int i=1;i<=m;i++)scanf("%d",&a[i]);
      f[1][1]=1.0;
      for(int i=2;i<=n;i++){
        for(int j=1;j<=i;j++){
          for(int k=1;k<=m;k++){
        int p,t=a[k]%i;
        if(t==0)t=i;
        if(t==j)continue;
        if(t>j)p=i-t+j;
        else p=j-t;
        f[i][j]+=f[i-1][p]/m;
          }
        }
      }
      printf("%.2lf%%",f[n][1]*100);
      for(int i=2;i<=n;i++)printf(" %.2lf%%",f[n][i]*100);
      return 0;
    }
    
    
  • 相关阅读:
    SpringFlex框架搭建
    SqlDataReader的用法 转自https://www.cnblogs.com/sunxi/p/3924954.html
    C#学习笔记:ListBox控件的用法
    C#栈Stack的使用
    C# 队列Queue
    xshell传送文件
    Java基础中字符串与字符的注意点!
    大数据的基础学习:
    Python的空行
    Python基本语法
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8407184.html
Copyright © 2011-2022 走看看