说我有10个奖品给100个人。每个人一次射击一次。因此,如果第一个人未能赢得奖品,则概率会上升,99分中为10分,所以一个......所有10个奖项必须去。
最好的方法是以最终的方式写这个,如果还剩下奖品,那么这个人将有一个机会获得奖品......
我的想法是这样的:
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个玩家取胜。
答案 0 :(得分:3)
每个人都有平等的获胜机会吗?在这种情况下,为什么不只是随机选择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);
}
答案 1 :(得分: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--;
}
}
编辑:证明这有效:
答案 2 :(得分:1)
这将为您提供强制获胜者的概率随着人数减少而变为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--;
}
答案 3 :(得分:0)
完美公平的方法是生成一个从1到(100!/(90!* 10!))的随机数(因为这是获奖者可能组合的数量)并用它来奖励奖品。
然而,使用该数字的某些倍数更容易,例如获奖者的排列数,即(100!/ 90!)。这样做的一种方法是填充100个整数的数组,但每次从数组中删除获胜的整数(用最后一个非获胜整数交换它是实现此目的的最简单方法)。
您的算法有效地需要100的随机性!所以效率低得多,虽然我认为它仍然完全公平。