【问题标题】:Random Probability Selection随机概率选择
【发布时间】:2011-10-20 10:10:35
【问题描述】:

假设我有 10 个奖品要送给 100 个人。每个人都得到一个镜头,一次一个。因此,如果第一个人未能中奖,则概率会上升,99 分之 10,等等……而且所有 10 个奖品都必须取消。

最好的写法是这样写,如果最后还有奖品,那个人将有 1 比 1 的机会获得奖品...

我是这样想的:

int playersLeft = 100
int winners = 0

while (winners < 10)
    winners += (random.Next(playersLeft--)<(10-winners)) ? 1 : 0;

我想知道是否有更好或更直接的方法来做到这一点。我知道这看起来很简单,但这个简单的任务是应用程序一个非常重要的方面的一部分,它一定是正确的。

澄清:我为什么要做这样的事情:

实际上有无限数量的玩家,每个人都有 X 比 Y 的概率获胜,比如 10/100 = 10%。但是,如果我将其留给随机数生成器,则有可能在 100 名玩家中,只有 9 人会获胜,或者最坏的情况是 11 人。在我的应用程序中,我必须确保每 100 名玩家不会超过或不少于 10 人赢了。

【问题讨论】:

  • 您是否意识到,如果您这样做,加入游戏会有更好和更坏的时刻吗?
  • @obrok - 是的,我知道。但任何其他方式,我必须根据情况来操纵它。例如,如果没有赢得任何价格,则强制每 X 数量的玩家获胜,或者如果已赢得所有价格,则指定在游戏期间不能再有获胜者。这就是为什么我想平均分配整个游戏的赢家。假设有 1000 名玩家,请确保前 100 人比后 100 人有 = 机会。与第 900 人给出所有价格相反,所以最后 100 人获胜的机会为 0。我不知道我是否说清楚了。
  • 而且不可能等到 100 名玩家到达并分发奖品,是吗?
  • 不...获胜者可以随时领取他们的奖品,他们必须在完成比赛后立即被选为获胜者或更松。

标签: c# random probability


【解决方案1】:

每个人都应该有平等的获胜机会吗?在那种情况下,为什么不随机选择 10 个不同的数字 1-100,然后假装按顺序做呢?

var winners = new HashSet<int>();
while(winners.Count < 10)
{
  var number = random.Next(100);
  if(!winners.Contains(number)) winners.Add(number);
}

for(i = 0; i < 100; i++)
{
  if(winners.Contains(i)) Console.WriteLine("{0} won!!!", i);
  else Console.WriteLine("{0} didn't win, sorry...", i);
}

【讨论】:

  • 为了简单起见,我把它放在一个while循环中。然而,选择将在很长一段时间内进行,这种方法需要我将预选保存在数据库中,我宁愿不这样做......但是谢谢......但是你是对的,我的方法,并非所有玩家都有相同的获胜机会。
【解决方案2】:

我对此进行了更多思考,并提出了以下建议。我们可以给第一个人一个公平的获胜机会,然后如果其余的奖励公平地分配给其他人(无论他是赢还是输),整个事情就会是公平的。当然,这远非正式证明,所以请随时纠正我。下面应该给出一个公平的系统:

int prizes = 10;
for(int i = 100; i >= 1; i++)
{
  var result = random.Next(people);
  if(result < prizes)
  {
     Console.WriteLine("{0} won", i);
     prizes--;
  }
}

编辑:证明这是有效的:

  1. 第一人微乎其微地有 n/k 获胜的机会(n 是奖品数量,k 是人数。
  2. 假设我们将剩余的奖品公平地分配给其他人。在这种情况下,他们将有概率 n/kn-1 个奖品在他们之间分配,概率为 (kn)/k,n 个奖品。这加起来平均为 (n*(n-1))/k + (n*(kn))/k = n*(k-1)/k,这是他们的公平份额奖品。
  3. 我们使用相同的方法在 k-1 人中分配 n-1n 个奖品。 Q.E.D.

【讨论】:

  • 我假设 people = i... 是的,这更像是我正在寻找的东西,谢谢。
【解决方案3】:

最公平的做法是生成一个从 1 到 (100! / (90! * 10!)) 的随机数(因为这是可能的获奖者组合的数量)并用它来颁发奖品。

但是,使用该数字的某个倍数会更容易,例如获奖者的排列数,即 (100! / 90!)。一种方法是填充一个包含 100 个整数的数组,但每次都从数组中删除获胜的整数(将其与最后一个未获胜的整数交换是实现此目的的最简单方法)。

您的算法实际上需要 100 的随机性!所以它的效率要低得多,尽管我相信它仍然是完全公平的。

【讨论】:

    【解决方案4】:

    这将使您在人数减少时强制获胜的概率变为 1.0。然而,正如@obrok 所指出的,一个人中奖的概率取决于他们在 100 人名单中的排名。

    这实际上与用于“N 选择 K”子集选择的算法相同。 http://mcherm.com/permalinks/1/a-random-selection-algorithm

    int prizes = 10;
    int people = 100;
    
    while ( prizes > 0 ) {
       double probOfWin = (double) prizes / people; 
       if ( random.NextDouble() <= probOfWin ) {
          prizes--;
       }
       people--;
    }
    

    【讨论】:

    • 是的,这与我的建议几乎相同......我只是试图保持所有人的概率相等,但同时确保赢得的奖品数量准确...... . 谢谢...
    • 其实我应该更准确些。每个人获胜的边际概率是相同的,但是给定先前获胜者的条件获胜概率是不均匀的,即让第n个人的x[n] k为奖品数量,N为总人数。对于这个选择算法,p(x[n] = WINNER) = k/N,但是 p(x[n] = WINNER | x[0], ..., x[n-1]) = (k - #迄今为止的获胜者)/(N - n)
    猜你喜欢
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 2011-02-15
    • 2019-05-10
    • 1970-01-01
    • 2013-08-27
    相关资源
    最近更新 更多