平均分组问题,类似装箱问题,php

来源:互联网 发布:python 交易策略 编辑:程序博客网 时间:2024/04/29 13:59

<?php


!<<<目前只实现了分2组的情况>>>!

/**
 * 按分数对选手进行平均分组,可分多组。
 *
 * 
 * 注意:
 * 1. 输入的选手名单players为集合形式,player表示选手名称,score表示选手的分数
 * 2. 选手的分数体现选手的实力,分数有可能是负数
 * 3. 最终解不是唯一,但要求分组后,每组的实力尽量接近,每组的人数也尽量接近
 *
 * 例如:
 * 将所有选手,总共7人
 * [
 *     {
 *         "player": "a",
 *         "score": 22
 *     },
 *     {
 *         "player": "b",
 *         "score": -9
 *     },
 *     {
 *         "player": "c",
 *         "score": 13
 *     },
 *     {
 *         "player": "d",
 *         "score": 17
 *     },
 *     {
 *         "player": "e",
 *         "score": 0
 *     },
 *     {
 *         "player": "f",
 *         "score": -11
 *     },
 *     {
 *         "player": "g",
 *         "score": -2
 *     }
 * ]
 * 分成两组,应该为4 vs 3的队形
 * [
 *   [
 *     {
 *       "player": "a",
 *       "score": 22
 *     },
 *     {
 *       "player": "e",
 *       "score": 0
 *     },
 *     {
 *       "player": "g",
 *       "score": -2
 *     },
 *     {
 *       "player": "f",
 *       "score": -11
 *     }
 *   ],
 *   [
 *     {
 *       "player": "d",
 *       "score": 17
 *     },
 *     {
 *       "player": "c",
 *       "score": 13
 *     },
 *     {
 *       "player": "b",
 *       "score": -9
 *     }
 *   ]
 * ]
 * 分成3组,应该为3 vs 2 vs 2的队形
 * [
 *   [
 *     {
 *       "player": "a",
 *       "score": 22
 *     },
 *     {
 *       "player": "b",
 *       "score": -9
 *     },
 *     {
 *       "player": "f",
 *       "score": -11
 *     }
 *   ],
 *   [
 *     {
 *       "player": "c",
 *       "score": 13
 *     },
 *     {
 *       "player": "e",
 *       "score": 0
 *     }
 *   ],
 *   [
 *     {
 *       "player": "d",
 *       "score": 17
 *     },
 *     {
 *       "player": "g",
 *       "score": -2
 *     }
 *   ]
 * ]
 *
 */


namespace Interview;


class AverageGroup
{
    
private $players = array();
private $count = 2;

/**
* @param [array] 选手名单
* @param [integer] 分组数
*/
function __construct($players, $count = 2) {
$this->players = $players;
$this->count = $count;
}


/**
* @return [array] 分组后的结果
*/
/*
* 思路:
* 元素替换法
* 默认把倒叙排列的数组分成两个数组,最大的$quantity个为一组,剩下最小的为另外一组,
* 依次用最小的里面的最大的元素替换最大的组里的最小的,然后对数组求和,
* 把和跟平均数比较,如果最大的数组的和小于等于平均数,就停止,返回最大的数组,
* 利用array_diff()得到另外一个数组。
*/
public function divide($group = array(),$count=2) {
   $group_score = array();
   //转换成只有score的一维数组
   foreach ($group as $gro){
       foreach ($gro as $k=>$v){
           if($k=="score"){
               array_push($group_score, $v);
           }
       }
   }
$con = count($group_score); 
$quantity = round($con/$count); //每组的人数
$sum = array_sum($group_score);
$average = round($sum/$count); // 分数取平均
rsort($group_score); //数组倒叙排列


$big_array = array();
for($a=0;$a<$quantity;$a++){
   array_push($big_array, $group_score[$a]);
}
$small_array = array();
$small_array = array_diff($group_score, $big_array);

        for($a=$con-$quantity;$a>=0;$a--){
            if(array_sum($big_array)>$average){
                for($b=$quantity;$b<$con;){
                    list($big_array[$a],$small_array[$b])=array($small_array[$b],$big_array[$a]);
                    if(array_sum($big_array)>$average){
                        $b++;
                    }else {
                        break;
                    }
                }
            }
        }
//还原数组
$big = array();
$small = array();
foreach ($group as $gro){
   foreach ($gro as $k=>$v){
       if($k=="score"){
           if(in_array($v, $big_array)){
               $big []= $gro;
           }else{
               $small []= $gro;
           }
       }
   }
}
print_r($big);
print_r($small);
}
}
0 0