如何在M队之间划分N个参与者,以便形成最小的对?

时间:2015-05-05 21:26:01

标签: algorithm

如果我有两个号码,即NM,我必须找出如何在N个小组中划分M人,以便最少对在每个团队中形成,然后我该怎么办呢? (此外,每个团队应至少有一名成员)

例如,如果我有N = 6M = 3, 那么,每个团队应该有2个人。因此,共有3支队伍,意味着3对队伍。

我知道我必须分发,以便分发应尽可能均匀。但是我无法为它提出合适的算法。谢谢!

3 个答案:

答案 0 :(得分:1)

这很简单。首先,在每个团队中加入n/m人。
你剩下n%m(n modolus m)的玩家,将他们随机分成小组,但是每个小组都可以获得其中一个"额外的"播放器。

直觉为什么这是真的很简单,在m = 2的情况下:

您需要将n个玩家分成xn-x,并且您希望最小化对数:

x(x-1)/2 + (n-x)(n-x-1)/2 = 
= (x^2-x + n^2 -2nx + x^2 -n +x)/2

使用衍生物查找最小值:

d(x^2-x + n^2 -2nx + x^2 -n -x)/2/dx = 2x -1 -2n +2x +1 = 4x-2n

看看上面的等于0:

4x-2n = 0 -> x=n/2

对于任何n/m,结果都会相似(尽可能接近m>0),更难以证明。

答案 1 :(得分:0)

与另一个答案类似,但有一个更直接的证据的大纲。假设你有两个队员,他们的队员数量差异超过1,即一队有k队员,一队有k + j队员,其中k> = 1且j> = 2。表明如果你将一个玩家从拥有k + j玩家的团队移动到拥有k个玩家的团队,那么你将使用二项式系数得到一个严格较小数量的对。

答案 2 :(得分:0)

  1. 已完成的团队数量= n / m
  2. 没有任何团队的玩家数量:n % m
  3. 现在您有两个选择:

    1. 创建一个由剩余玩家组成的新团队。
    2. 再给每个队伍增加一名球员,直到你没有单独的球员。
    3. 我知道你选择了选项2.

      我将向您展示Java中可能对您有帮助的代码。

      (我知道你的问题没有java标签,但是很容易理解的高编程语言)

      int people = n;
      int numberOfTeams = m;
      int peopleAlone = n;
      
      int initialPeopleForTeam = n/m;
      
       //This is an array of teams where each element of array is a team,
      // and his value the number of people that have the team.
              int teams[] = new int [numberOfTeams];
      
      
      //each team starts with n/m players. 
           for (int i = 0; i < m; i++){
              teams[i] = initialPeopleForTeam;
              peopleAlone = peopleAlone - initialPeopleForTeam;
          }
      
       //While the number of people alone is not 0, I'll give one more  person  to each team.
            int index = 0;
            while (peopleAlone > 0){
            teams[index] = teams[index] + 1;
            index++;
            peopleAlone--;
           }