我正在尝试让我的应用程序确定将20个高尔夫球手分组为四人一组的最佳解决方案。
我有数据显示高尔夫球手打球的时间,日期和组中的其他人。
我希望由未参加比赛的高尔夫球手组成的小组,或者当每个人都一起参加比赛时,他们在一起比赛的时间最长。换句话说,我希望由不曾一起上场而不是上一次比赛的球员组成的小组。
创建一个20的排列列表!确定最低的组合效果不佳。
我还有没有想到的其他解决方案?
最佳答案
@ Salix-alba的答案可以帮助您入门。基本上,您需要一种方法来计算您的高尔夫团队成员已经花费了多少时间。为了举例说明,我假设您有一种方法来确定两个高尔夫球手在一起花费了多少时间。该算法可以总结为:
计算每组四个高尔夫球手在一起的总时间(请参阅Salix-alba的答案),并按顺序存储结果。
选择时间最短的四个高尔夫球手作为第一组。
继续从可能的组的有序列表中选择组,以使下一个组的成员都不是任何先前组的成员
当所有高尔夫球手归为一组时,停止运行,这总是在您用尽所有可能的组合之前发生。
通过快速的方式,不要答应编译示例(我直接在答案窗口中写了它):
假设您有一个方法time(a,b)
,其中a
和b
是高尔夫球手身份,结果是两个高尔夫球手在一起花费了多少时间。
还要假设我们将使用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
将具有许多集合,每个集合代表一个播放组。显然,您可以调整权重函数以得到不同的结果-说您宁愿关注最小化自小组成员一起玩起的时间。在那种情况下,不使用上场时间,而是将组中每个成员自上次比赛以来的时间加起来,以任意大但合理的值表示他们是否从未参加比赛,而不是找到最少的组,而是找到最大的组。等等。
希望这对您有所帮助!