根据以前的数据创建组

时间:2014-03-21 19:16:30

标签: java math combinations permutation

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

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

我希望那些由高尔夫球手组成的小组,他们没有一起比赛,或者每个人都在一起比赛,这是他们一起比赛的最长时间。换句话说,我希望由一群玩家组成的小组在一段时间内一起玩,而不是上一次。

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

我还有其他解决方案吗?

2 个答案:

答案 0 :(得分:2)

应该有20个C 4可能的分组,即4845.应该可以使用四个嵌套的for循环很容易地生成这些组合。

int count = 0;
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) {
                System.out.println(""+i+"\t"+j+"\t"+k+"\t"+l);
                ++count;
            }
        }
    }
}
System.out.println("Count "+count);

您可以快速遍历所有这些并使用一些目标函数进行锻炼,这是最佳分组。你的问题定义有点模糊,所以我不确定如何判断哪个是最好的组合。

这就是从20个中挑选四个高尔夫球手的方式,你真的需要5组4我认为是20C4 * 16C4 * 12C4 * 8C4这是305,540,235,000。尽管您可能需要等待几分钟,但这仍然是详尽无遗的计算领域。

另一种方法可能是概率方法。只需随机选择群组,拒绝非法组合以及不符合条件的群组。继续挑选随机组,直到找到足够好的组。

答案 1 :(得分:2)

@ Salix-alba的回答是让你开始的答案。基本上,你需要一种方法来计算你的高尔夫球队成员已经花了多少时间。我假设你有一个方法来确定两个高尔夫球手一起度过多少时间。然后可以将算法总结为:

  1. 计算每组4名高尔夫球手共同度过的总时间(参见Salix-alba的回答),以有序的方式存储结果。

  2. 选择一组时间最少的4名高尔夫球手作为第一组。

  3. 继续从您订购的可能群组列表中挑选群组,以便下一个群组中的任何成员都不是之前任何群组的成员

  4. 当所有高尔夫球手都有一个小组时停止,这将在你用完可能的组合之前一直发生。

  5. 通过快速,不承诺编译的例子(我直接在答案窗口中写了):

    假设你有一个方法time(a,b),其中ab是高尔夫球手的身份,结果是两个高尔夫球手一起度过的时间。< / p>

    还假设我们将使用TreeMap&gt;跟踪&#34;权重&#34;与分组相关联,以有序的方式。

    现在,让我们使用上述假设构建我们小组的权重:

    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将有许多集合,每个集合代表一个游戏组。

    显然,您可以调整权重函数以获得不同的结果 - 比如说您宁愿关注最小化自小组成员一起玩的时间。在这种情况下,不是使用游戏时间,而是为上一次游戏中的每个成员总结一些具有一些任意大但合理的值以指示他们是否从未玩过的时间,而不是找到最小的组,找到最大的。等等。

    我希望这是一本有用的入门书!