【问题标题】:divide n players to m teams to minimize the team difference in Java将 n 个玩家分成 m 个团队以最小化 Java 中的团队差异
【发布时间】:2013-07-10 15:57:08
【问题描述】:

我遇到了一个问题,我需要一些聪明的 SO 的帮助。我想将 n 个玩家分成 m 个团队。每个玩家都有不同的游戏能力。能力由正整数或负整数表示。一个团队的总能力只是分配到该团队的人员的能力得分之和。

我的目标是找到总能力最大的团队和总能力最小的团队之间的最小可能差异。限制条件是每个球员都必须被安排在一个团队中,并且每个团队必须至少有一个成员。

例如,如果我有以下具有能力的球员:[1, 2, 3, 4, 5, 6, 7] 并想组成三支球队。因此,总能力最大的团队和总能力最小的团队之间的最小可能差异为 1。一种可能的解决方案是:

第 1 队:1 + 3 + 6 = 10

第 2 队:2 + 7 = 9

第 3 队:4 + 5 = 9

我尝试使用以下策略来划分玩家:

1.对能力进行排序

2.每次将剩余能力最高的玩家分配到能力最低的组中,直到没有玩家为止

此策略适用于某些问题。这是我到目前为止的代码:

public int minDifference(int numTeams, int[] abilities) {
        ArrayList<ArrayList<Integer>> teams = new ArrayList<ArrayList<Integer>>();
        int[] teamSum = new int[numTeams];
        for(int i = 0; i < numTeams; i++){
            teams.add(new ArrayList<Integer>());
            teamSum[i] = 0;
        }
        Arrays.sort(abilities);
        for(int i = abilities.length - 1; i >= 0;  i--){
            int minSum = teamSum[0];
            int minNum = 0;
            for(int j = 1; j < numTeams; j++){
                if(teamSum[j] < minSum){
                    minSum = teamSum[j];
                    minNum = j;
                }
            }
            teams.get(minNum).add(abilities[i]);
            teamSum[minNum] += abilities[i];
        }
        Arrays.sort(teamSum);
        System.out.println(teamSum[numTeams - 1] - teamSum[0]);
        return teamSum[numTeams - 1] - teamSum[0];
    }

现在我被困住了。我的想法是比较两支球队。说 A 和 B。A 的玩家 Tom 和 B 的玩家 Jerry。如果 A - B = 10,并且 Tom - Jerry = 3;然后交换汤姆和杰瑞。所以 A - B = 4 现在。并继续这样做。但是好像比较太多了(因为你还需要计算两队球员之间的差异),我不知道什么时候停止(意味着我怎么知道它是最小的)。

【问题讨论】:

  • 对不起,如果问题不清楚。我想将n个玩家分成m个队,最小化能力最高的团队和能力最低的团队之间的能力差异。
  • 您自己尝试过吗?如果是这样,你能分享它并解释你需要帮助的地方吗? SO 不是编码或算法服务,我们不是来解决您的问题,只是为了回答您的问题。
  • 告诉我们what you have tried,我们可以为您提供帮助。我们不是代码编写服务(我们中有些人通过编写代码赚钱)。
  • “我想要 ..” 提示。一个问题可能以“如何……”开头,并且通常以“?”结尾。你提出的问题越清楚,得到回答的机会就越大。如果这是你的问题,请edit它进入问题。
  • 你对数组的大小有限制吗?对于较小的数字,蛮力可能是合理的。否则,这可能是一个没有“精确”算法的优化问题。您的尝试(嗯,至少是您的描述)通常被称为“爬山”。这是 wikipedia 关于优化算法的参考:en.wikipedia.org/wiki/…。这里有一个类似的问题:stackoverflow.com/questions/14120729/…

标签: java algorithm recursion


【解决方案1】:

我是这样想的。您可以将所有能力相加并除以团队数量,而不是尝试提出总能力尽可能接近该数字的团队

【讨论】:

  • 是的,但是您能否澄清一下“然后尝试提出总能力尽可能接近该数字的团队”?他和以前有同样的问题(蛮力方法或更聪明的算法,然后......哪个?)
  • 保留所有能力的“大”列表,并为每个团队制作一个列表并执行以下操作。你有团队所需的能力。在“大”列表中找到最接近的能力,将其从“大”列表中删除,将其添加到团队的列表中,更新所需的能力递归执行直到所需的能力 = 0 左右……为每个团队执行……其中之一可能的策略。
  • 不,这将是一个很好的选择只为一队(其他人将只能选择前辈没有使用过的东西)。不是组合可以最大限度地减少差异。
  • 我认为,无论如何这个问题都无法有效解决,这是一种启发式方法,在某些情况下可以给出满意的答案
  • 查看我对问题和相关链接的评论。当然,复杂性很快就会增加,将 M 增加到不可接受的水平(然后可能需要一些启发式)。也就是说...启发式不能太原始(= 它必须足够好,IMO 你的方法不是)。
【解决方案2】:

我很确定这是一个 NP 问题,因为我们是否可以将玩家分成 2 个没有区别的团队的决定是属于 NPC 的subset-sum problem。这个问题的任何多项式时间解决方案都是不正确的(或者你可以说 NP=P),所以不要浪费时间思考多项式解决方案,只需尝试完整搜索(我的意思是所有 m^n 可能的解决方案..),如果你觉得太慢了,可以试试启发式搜索。

【讨论】:

  • 可能存在从子集和到 OP 问题的减少,但我认为这不是显而易见的问题。使用子集和,所有负整数都到一个团队(比如 A),所有非负整数到另一个团队(比如 B)。然后你会试图找出一个 A 的子团队,其总和等于 B 的总和(在大小上)的一个子团队。在这个问题中,每个团队都有精确的限制(数组大小)/(团队数量)。此外,您不能将数组的元素限制为只有一个团队。很难说清楚,但“明显减少”似乎不起作用。
猜你喜欢
  • 1970-01-01
  • 2013-11-23
  • 1970-01-01
  • 1970-01-01
  • 2019-06-26
  • 2021-04-30
  • 2016-08-08
  • 2021-04-11
  • 2021-11-02
相关资源
最近更新 更多