你的问题很有挑战性,但我找到了一个可行的(也许不是最高效的)解决方案。我的示例是用 PHP 编写的,但您应该能够适应它。我将尝试解释代码背后的“想法”。
注意:似乎您稍后添加了“10 人,3 个工作”约束——或者我只是过度阅读了它。但是,我的代码应该为您提供一个示例,您可能能够适应该约束。我的代码目前假设有人有n
工作n
。(将其调整为 10/3 标准的最简单方法是将 3 个工作分成 10 个相等的工作单元,假设有 10 个工人!)
首先,让我们创建一些基本架构的东西。我们需要person
,job
显然是一个矩阵,代表一个人对工作的满意度。以下片段正是这样做的:
<?php
class Person{
var $name;
var $prim;
var $sec;
function __construct($name, $prim, $sec){
$this->name = $name;
$this->prim = $prim;
$this->sec = $sec;
}
function likes($job){
if ($job->type == $this->prim) return 2;
if ($job->type == $this->sec) return 1;
else return -1;
}
}
class Job{
var $name;
var $type;
function __construct($name, $type){
$this->name = $name;
$this->type = $type;
}
}
$persons = array(
"Max" => new Person("Max", "programing", "testing"),
"Peter" => new Person("Peter", "testing", "docu"),
"Sam" => new Person("Sam", "designing", "testing")
);
$jobs = array(
"New Classes" => new Job("New Classes", "programing"),
"Theme change" => new Job("Theme change", "designing"),
"Test Controller" => new Job("Test Controller", "testing")
);
// debug: draw it:
echo "<h2>Happines with Jobs</h2> ";
echo "<table border=1>";
$p=0;
echo "<tr>";
foreach ($jobs AS $job){
$j=0;
foreach ($persons as $person){
if ($p++==0){
echo "<tr><td></td>";
foreach ($persons as $per) {
echo "<td>".$per->name."</td>";
}
echo "</tr>";
}
if ($j++==0){
echo "<td>".$job->name."</td>";
}
echo "<td>".$person->likes($job)."</td>";
}
echo "</tr>";
}
echo "</table>";
这会给你一个像这样的表:
其次,我们需要创建工作和人员的所有排列。(实际上我们不需要,但这样做会告诉你原因,为什么我们不需要!)
要创建所有排列,我们只使用一个人或工作的名称。(我们可以稍后将名称解析回实际对象)
//build up all permutations
$personNames = array();
foreach ($persons AS $person){
$personNames[] = $person->name;
}
$jobNames = array();
foreach ($jobs AS $job){
$jobNames[] = $job->name;
}
$personsPerms = array();
pc_permute($personNames,$personsPerms);
$jobsPerms = array();
pc_permute($jobNames,$jobsPerms);
function pc_permute($items, &$result, $perms = array( )) {
if (empty($items)) {
$result[] = join('/', $perms);
} else {
for ($i = count($items) - 1; $i >= 0; --$i) {
$newitems = $items;
$newperms = $perms;
list($foo) = array_splice($newitems, $i, 1);
array_unshift($newperms, $foo);
pc_permute($newitems,$result, $newperms);
}
}
}
现在,我们有 2 个数组:所有工作排列和所有人员排列。对于上面给出的示例,数组将如下所示(每个 3 个元素,每个数组有 3*2*1=6 个排列):
Array
(
[0] => Max/Peter/Sam
[1] => Peter/Max/Sam
[2] => Max/Sam/Peter
[3] => Sam/Max/Peter
[4] => Peter/Sam/Max
[5] => Sam/Peter/Max
)
Array
(
[0] => New Classes/Theme change/Test Controller
[1] => Theme change/New Classes/Test Controller
[2] => New Classes/Test Controller/Theme change
[3] => Test Controller/New Classes/Theme change
[4] => Theme change/Test Controller/New Classes
[5] => Test Controller/Theme change/New Classes
)
现在,我们可以创建一个nXn
表,其中包含所有可能的工作分配的总体满意度的所有值:
// debug: draw it:
echo "<h2>Total Happines of Combination (full join)</h2> ";
echo "<table border=1>";
$p=0;
echo "<tr>";
$row = 0;
$calculated = array();
foreach ($jobsPerms AS $jobComb){
$j=0;
$jobs_t = explode("/", $jobComb);
foreach ($personsPerms as $personComb){
if ($p++==0){
echo "<tr><td></td>";
foreach ($personsPerms as $n) {
echo "<td>".$n."</td>";
}
echo "</tr>";
}
if ($j++==0){
echo "<td>".$jobComb."</td>";
}
$persons_t = explode("/", $personComb);
$h = 0;
echo "<td>";
for ($i=0; $i< count($persons_t); $i++){
$h += $persons[$persons_t[$i]]->likes($jobs[$jobs_t[$i]]);
}
echo $h;
echo "</td>";
}
$col=0;
$row++;
echo "</tr>";
}
echo "</table>";
让我们称这个矩阵为“M”
该矩阵包含“很多”双重组合:(a/b) TO (1/2) 等于 (b/a) 到 (2/1) 等等...
毕竟:我们简单可以忽略:
忽略所有 > 1 的列:
echo "<h2>Total Happines of Combination (ignoring columns)</h2> ";
echo "<table border=1>";
$p=0;
echo "<tr>";
$row = 0;
$calculated = array();
foreach ($jobsPerms AS $jobComb){
$j=0;
$jobs_t = explode("/", $jobComb);
$col = 0;
$personComb = $personsPerms[0];
if ($p++==0){
echo "<tr><td></td>";
echo "<td>".$personsPerms[0]."</td>";
echo "</tr>";
}
if ($j++==0){
echo "<td>".$jobComb."</td>";
}
$persons_t = explode("/", $personComb);
$h = 0;
echo "<td>";
for ($i=0; $i< count($persons_t); $i++){
$h += $persons[$persons_t[$i]]->likes($jobs[$jobs_t[$i]]);
}
echo $h;
echo "</td>";
$col=0;
$row++;
echo "</tr>";
}
echo "</table>";
输出:
你去吧!在这个例子(之一)中,最令人满意的解决方案是:
- 最大 -> 新课程 (+2)
- 彼得 -> 测试控制器 (+2)
- Sam -> 主题变化 (+2)
-> 幸福:6。
还有其他相等的分布。
示例:6 人 / 6 份工作:
$persons = array(
"Max" => new Person("Max", "programing", "testing"),
"Peter" => new Person("Peter", "testing", "docu"),
"Sam" => new Person("Sam", "designing", "testing"),
"Jeff" => new Person("Jeff", "docu", "programing"),
"Fred" => new Person("Fred", "programing", "designing"),
"Daniel" => new Person("Daniel", "designing", "docu")
);
$jobs = array(
"New Classes" => new Job("New Classes", "programing"),
"Theme change" => new Job("Theme change", "designing"),
"Test Controller" => new Job("Test Controller", "testing"),
"Create Manual" => new Job("Create Manual", "docu"),
"Program more!" => new Job("Program more!", "programing"),
"Style the frontend" => new Job("Style the frontend", "designing")
);
结果(人:Max / Peter / Sam / Jeff / Fred / Daniel)