我正在尝试让我的应用程序确定将20个高尔夫球手分组为四人一组的最佳解决方案。

我有数据显示高尔夫球手打球的时间,日期和组中的其他人。

我希望由未参加比赛的高尔夫球手组成的小组,或者当每个人都一起参加比赛时,他们在一起比赛的时间最长。换句话说,我希望由不曾一起上场而不是上一次比赛的球员组成的小组。

创建一个20的排列列表!确定最低的组合效果不佳。

我还有没有想到的其他解决方案?

最佳答案

@ Salix-alba的答案可以帮助您入门。基本上,您需要一种方法来计算您的高尔夫团队成员已经花费了多少时间。为了举例说明,我假设您有一种方法来确定两个高尔夫球手在一起花费了多少时间。该算法可以总结为:


计算每组四个高尔夫球手在一起的总时间(请参阅Salix-alba的答案),并按顺序存储结果。
选择时间最短的四个高尔夫球手作为第一组。
继续从可能的组的有序列表中选择组,以使下一个组的成员都不是任何先前组的成员
当所有高尔夫球手归为一组时,停止运行,这总是在您用尽所有可能的组合之前发生。


通过快速的方式,不要答应编译示例(我直接在答案窗口中写了它):

假设您有一个方法time(a,b),其中ab是高尔夫球手身份,结果是两个高尔夫球手在一起花费了多少时间。

还要假设我们将使用TreeMap>以排序的方式跟踪与组关联的“权重”。

现在,让我们使用以上假设来构造各组的权重:

TreeMap<Integer,Collection<Integer>> options = new TreeMap<Integer, Collection<Integer>>();
for(int i=0;i<17;++i) {
    for(int j=i+1;j<18;++j) {
        for(int k=j+1;k<19;++k) {
            for(int l=k+1;l<20;++l) {
                Integer timeTogether = time(i,j) + time(i,k) + time(i,l) + time(j,k) + time(j,l)+time(k,l);
                Collection<Integer> group = new HashSet<Integer>();
                group.add(i);
                group.add(j);
                group.add(k);
                group.add(l);
                options.put(timeTogether, group);
            }
        }
    }
}
Collection<Integer> golferLeft = new HashSet<Integer>(); // to quickly determine if we should consider a group.
for(int a=0; a < maxGolfers, a++) {
    golferLeft.add(a);
}

Collection<Collection<Integer>> finalPicks = new ArrayList<Collection<Integer>>();
do{
    Map.Entry<Integer, Collection<Integer>> least = options.pollFirstEntry();
    if (least != null && golferLeft.containsAll(least.getValue()) {
        finalPicks.add(least.getValue());
        golferLeft.removeAll(least.getValue());
    }
}while (golferLeft.size() > 0 && least != null);


在最后循环的最后,finalPicks将具有许多集合,每个集合代表一个播放组。

显然,您可以调整权重函数以得到不同的结果-说您宁愿关注最小化自小组成员一起玩起的时间。在那种情况下,不使用上场时间,而是将组中每个成员自上次比赛以来的时间加起来,以任意大但合理的值表示他们是否从未参加比赛,而不是找到最少的组,而是找到最大的组。等等。

希望这对您有所帮助!

09-11 18:07