当前位置: 首页 > 知识库问答 >
问题:

产生更强团队的最佳算法

韦业
2023-03-14

我得到了一份0-100人的球员名单和一份拥有自己所有成员名单的球队名单。

现在我想把球员放在团队中,这样团队的大小基本相同(-1差异是可以的),并且技能的总和应该尽可能接近。

我目前的解决方案是一个简单的投票算法(团队在圆圈中投票球员,然后选出下一个最佳球员):

public class Teamgenerator {
    public void calcTeams(){
        List<Team> teams = new ArrayList<>();
        teams.add(new Team("Team 1"));
        teams.add(new Team("Team 2"));

        List<Player> players = new ArrayList<>();
        players.add(new Player("Player 1",25));
        players.add(new Player("Player 2",50));
        players.add(new Player("Player 3",50));
        players.add(new Player("Player 4",75));

        int nextTeam = 0;
        while (players.size() > 0) {
            int bestPlayer = findBestPlayerIndex(players);
            teams.get(nextTeam).players.add(players.get(bestPlayer));
            players.remove(bestPlayer);

            if (nextTeam < teams.size() - 1) nextTeam++;
            else nextTeam = 0;
        }

        for(Team t:teams){
            System.out.println(t.getName()+":");
            for(Player p:t.players)
                System.out.println(p.getName()+", Skill "+p.getSkill());
        }
    }


    private int findBestPlayerIndex(List<Player> players) {
        //In my real programm i have to pick the skill of a more complex player object from a DB, 
        //depending on a specific competition,  which causes i really need this index finding
        int index = -1;
        int highestSkill=-1;
        for (int i = 0; i < players.size(); i++) {
            if (players.get(i).getSkill() > highestSkill) {
                highestSkill = players.get(i).getSkill();
                index = i;
            }
        }
        return index;
    }
}

public class Team {
    private String name;
    public ArrayList<Player> players=new ArrayList<>();

    public Team(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Player {
    private String name;
    private int skill=50; //From 0-100

    public Player(String name, int skill) {
        this.name = name;
        this.skill = skill;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSkill() {
        return skill;
    }

    public void setSkill(int skill) {
        this.skill = skill;
    }   
}

问题是,给出的不是最均匀的团队,控制台输出是:

球队1:球员4,技能75;玩家 3, 技能 50

第二队:球员2,技能50;球员1,技能25

但如果球队是4 1和球员3 2,那就更公平了。你对更公平的算法有什么想法吗?感谢您的帮助!

共有1个答案

公冶桐
2023-03-14

如YouTube所见——有史以来最公平的共享序列——苏莫尔斯序列站立数学可能是您最大限度地减少第一回合优势的最佳选择。

维基百科:

在数学中,Thue–Morse序列或Prouhet–Thue–Morse序列是一个二进制序列(0和1的无限序列),它是从0开始,然后依次附加到目前为止获得的序列的布尔补码。此过程的前几个步骤生成字符串0,然后是01、0110、01101001、0110100110010110,依此类推,它们是Thue–Morse序列的前缀。。。

计算机科学入门 - 普林斯顿

//Copyright © 2000–2016, Robert Sedgewick and Kevin Wayne. 
public class ThueMorse { 
   public static void main(String[] args) { 
        int n = Integer.parseInt(args[0]);
        String thue   = "0";
        String morse  = "1";

        for (int i = 1; i <= n; i++) {
            String t = thue;             // save away values
            String m = morse;
            thue  += m;
            morse += t;
        }
        System.out.println(thue);
    }
}

从Python答案移植,以获得版权认可的版本:

public static int whoseTurn(int turnCount){
    return Integer.bitCount(turnCount) % 2;
}

使用这个转弯顺序,根据技能水平排序的列表应该会给更公平的团队,并满足你在-1成员内的限制。

通过生成前 105 位数字,根据整数序列的在线百科全书 (A010060) 进行验证。

import java.util.stream.IntStream;

public class NodeStack {

public static int whoseTurn(int turnCount){
    return Integer.bitCount(turnCount) % 2;
}

public static void main(String[] args) {
    System.out.print("OEIS: ");
    IntStream.range(0,105).map(NodeStack::whoseTurn).forEach(i->System.out.print(i+", "));
    String result = IntStream.range(0,105).map(NodeStack::whoseTurn).collect(StringBuilder::new,(sb,i)->sb.append(i), StringBuilder::append).toString();
    System.out.println();
    IntStream.range(1,105).forEach(
            (i)-> System.out.println(i+"# "+result.substring(0,i)+ " : " +diff(result.substring(0,i)))
    );
}

public static int diff(String s){
    int zero = 0;
    int one = 0;
    for (char c:s.toCharArray()){
        if (c=='0')zero++;
        if (c=='1')one++;
    }
    return zero-one;
}

}
 类似资料:
  • 问题内容: 我正在寻找可满足以下所有要求的非常高要求的生产环境(商业或免费)中使用的Java Profiler: 与代码的轻量级集成(无需使用特殊选项进行重新编译,无需代码钩子等)。可以在应用程序代码旁边放一些探查器特定的.jar文件。 应该能够在不重新启动应用程序的情况下连接/断开与JVM的连接。 当分析处于活动状态时,对性能没有影响 启用性能分析后,对性能的影响可以忽略不计。轻微的降解是可以接

  • 我正在(用Java)研究递归图像处理算法,该算法从中心点向外递归遍历图像的像素。 不幸的是,这会导致堆栈溢出。所以我决定切换到基于队列的算法。 现在,这一切都很好,但是考虑到它的队列将在很短的时间内分析数千个像素,同时不断弹出和推送,而不保持可预测的状态(长度可能在100到20000之间),队列实现需要具有显著的快速弹出和推送能力。 链表似乎很有吸引力,因为它能够将元素推到自己身上,而无需重新排列

  • 问题内容: 我是ReactJS的新手,正在尝试了解什么是将代码部署到生产中的最佳方法。按照下面的链接,我正在使用babel作为下面的代码进行构建,但是我想知道 这是否很好,或者是否有 将ReactJS部署到生产中的 其他最佳实践 : http://www.sitepoint.com/getting-started-react- jsx/ 这是我的index.html和main.js文件: inde

  • 我正在使用RabbitMQ作为面向服务的体系结构中的消息队列,其中许多单独的web服务发布绑定到RabbitMQ队列的消息。这些队列依次由执行后台工作的各种消费者订阅;RabbitMQ的一个非常普通的用例。 现在我想更改一些队列参数(特别是,我想用某个路由键将队列绑定到一个新的死信交换)。我的问题是,由于以下几个原因,在生产系统上进行这种更改是有问题的。 在生产系统中不丢失消息的情况下,转换到这些

  • 我正在寻找一种非常简单的方法,用未知(但已知)数量的球员组建2支球队。因此,这实际上不是一个标准的配对,因为它只为特定的比赛在整个注册球员池中创建一场比赛。我几乎只有一个变量,它是每个球员的ELO分数,这意味着它是唯一可以用来计算的选项。 我想到的只是简单地检查每一个可能的球员组合(每队6名),球队平均ELO之间的最小差异是最终创建的名册。我已经测试过这个选项,它为18名注册玩家提供了超过1700

  • 问题内容: 我正在创建一个Web API,需要一种很好的方法来非常快速地生成一些格式正确的xml。我找不到在python中执行此操作的任何好方法。 注意:一些库看起来很有前途,但要么缺少文档,要么仅输出到文件。 问题答案: 使用lxml: 输出: 有关更多信息,请参见教程。