根据首选项列表分配组(Take 3)

时间:2013-09-23 19:37:19

标签: algorithm

这是从纯粹算法的角度出发的问题的第三次迭代,现在已经转向寻找我能理解的代码示例的绝望任务。

我要做的是创建人员列表的 g 组,尝试尽可能多地满足偏好。每个人都在列表中列出了他们希望分配的顶级 n 其他人的未排名列表。它(我的程序)需要将相互请求视为单向的更有影响力,并且(希望)找到接近最优解的东西。

我想要某种代码示例(实际上,任何基于C语言或详细的伪代码),以便我可以理解所需的算法并编写我的程序。在我的第一个问题之后,我已经确定这可能需要在稳定婚姻问题上使用某种变体,但我无法在伪代码或我能理解的实际语言中找到完整的例子。

我之前已经询问了有关算法HEREHERE的问题,但没有提出任何问题(我认为这是因为这些SE论坛上的用户数量非常少)。现在我在这里问一个问题,希望更高的观看率加上面向编程的问题能给我一个答案。

是的,我确实意识到之前已经提出过这样的问题,但没有一个问题既适用也适用。

有谁知道我该怎么做?

添加更多详细信息(以回应评论): 我有一份人员名单。对于每个人,我列出了他们对其他人的最高偏好,其中仅包括主列表中的其他人。没有列表以任何方式排序。首选项列表中的名称表示请求者希望与所请求的人员在一起。我正在寻找一种方法来创建指定数量的组,每个组只包含我在主列表中的人。我希望分组合并首选项列表。如果他们都在他们的列表中相互请求,它应该尝试将人们放在同一个组中。它还应该包含一个人(本例中的人A)请求其他人(人B)但B不请求A的请求。在这种情况下,虽然它仍应计算请求,但应将其视为较低优先考虑纳入而不是相互要求。

编辑: 同样,根据请求,这里有一个JS函数(希望)有助于解释我的目标:

/*
Scores a possible grouping
group would be an object, where the keys are names and the values are arrays of preferences. Ex:

    {
        "Person 1": ["Person 2"],
        "Person 2": ["Person 1"],
        "Person 3": ["Person 4"],
        "Person 4": ["Person 2"]
    }

*/
function getGroupScore(group) {
    var totalPoints = 0;

    //Add a point for each request
    for (var person in group) {
        for (var request in group[person]) {
            if(request != undefined && request.length > 0)
                totalPoints++;
        }
    }

    //Add two points for each two-way request
    for (var person in group) {
        for (var request in group[person]) {
            if (group[person][request] != undefined //String validation
                && group[person][request].length > 0 //More string validation
                && group[group[person][request]] != undefined //Array validation
                && group[group[person][request]].indexOf(person) != -1) //Check mutual request
                    totalPoints += 2;
        }
    }

    return totalPoints;
}

/*
Compares two possble groupings
*/
function compareGroups(groupA, groupB) {
    var scoreA = getGroupScore(groupA),
        scoreB = getGroupScore(groupB);

    if (scoreA > scoreB)
        return 1;
    else if (scoreA == ScoreB)
        return 0;
    else
        return -1;
}

1 个答案:

答案 0 :(得分:2)

好的,我一直在考虑你的问题,我想我可以给你一些方向,虽然我无法解决它。

首先,我会尝试稍微改写一下你的问题,如果我错了,请纠正我。

让一组P人和一个偏好表如:

Preferences of 4 people named A B C D:
   A B C D
 +---------+
A| X   X   |
B|       X |
C|     X X |
D|   X     |
 +---------+

在这个例子中,'A'更喜欢'C','B'更喜欢'D'等。对角线是否更喜欢自己将变得无关紧要。

现在你的问题是将P人分成G个不同的大小为N的集合,假设P = G * N.对于N = 2示例:

  A C B D
 +-------|
A|x x|   |
C|  x|  x|
 +---+----
B|   |  x|
D|   |x  |
 +---+---+
Here the partition is {A, C} and {B, D}

满足分区的程度是对角线块中X的数量之和,在上例中为3 + 2 = 5.

AFAIK,与您要解决的问题最相似的问题是构建一个块对角矩阵,或尽可能接近一个。在您的情况下,对角线块之外的值不会对您不利。

如果你强行解决问题,那么你有P!/ N!要检查的分区。对于小的P值和大的N值,这可能值得直接实现,尽管在JS中这样做会有害。如果你的解决方案必须是最佳结果,那么你可能不得不求助于这样的事情。

如果你可以允许“非常好”的解决方案,那么随机方法可能会接近。只做贪婪的重新排列,直到没有重新排列帮助,并重复几次。

我还在另一个论坛上发现了this thread,可能对您有所帮助。与此相关的大多数问题都假设存在满足每个偏好的解决方案,并且归结为广度优先搜索。显然,如果这是真的那么结果将是你的最佳解决方案,但是因为一般情况下你不太可能需要做一些繁重的研究来修改已知的算法。

祝福〜