将数组拆分为具有最小值和最小元素的组

时间:2016-07-01 13:32:50

标签: php

我有一个带有十进制值的数组,如下所示:

$a = array( 1.66, 28.13, 3.37, 2, 12, 88.90, 6.88, 0.57, 1.50 );

如何将此数组拆分为最少5个元素的组,这些元素的最小总和值为50!

我已经使用过这个功能,但并没有完全解决我想要做的事情。

function split_into_groups( $input_array ) {

  $limit = 50;
  rsort($input_array);
  $b = array(array());
  $index = 0;
  foreach($input_array as $i){
      if( $i + array_sum( $b[$index] ) > $limit){
          $b[++$index] = array();
      }
      $b[$index][] = $i;
  }
  return $b;
}

输出:

array(4) {
  [0]=>
  array(0) {
  }
  [1]=>
  array(1) {
    [0]=>
    float(88.9)
  }
  [2]=>
  array(3) {
    [0]=>
    float(28.13)
    [1]=>
    int(12)
    [2]=>
    float(6.88)
  }
  [3]=>
  array(5) {
    [0]=>
    float(3.37)
    [1]=>
    int(2)
    [2]=>
    float(1.66)
    [3]=>
    float(1.5)
    [4]=>
    float(0.57)
  }
}

2 个答案:

答案 0 :(得分:1)

这有点棘手,但我希望这是你所追求的。 代码中的注释应该具有足够的描述性,如果没有,我想发表评论。

<?php
$a = array( 1.66, 28.13, 3.37, 2, 12, 88.90, 6.88, 0.57, 1.50 );
// split into groups of at least 5 elements,
// each group must have sum of at least 50

// create array to hold arrays of groups:
$groups = array(0);

// initialize a counter to say which element of $groups to add to:
$group_selector = 0;

// this must be declared as an array, creating a multidimentional array:
$groups[$group_selector] = array();

// loop through each item in $a, deciding where to put it:
for ($i=0; $i < count($a); $i++) {

    // check if there is less than 5 elements in current group, OR the sum is less than 50:
    if ((count($groups[$group_selector]) < 5) || (array_sum($groups[$group_selector]) < 50)) {

        // add current $a item to current group:
        array_push($groups[$group_selector], $a[$i]);

    } else {
        // increment the group selector and declare it as a new array:
        $group_selector++;
        $groups[$group_selector] = array();
        array_push($groups[$group_selector], $a[$i]);
    }

} # end of main for loop

// print the raw array (doesn't look very good):
print_r($groups);

echo '<br><br>';

// print the sum of each group, and the number of items it contains:
for ($i=0; $i < count($groups); $i++) {
    echo 'count: ' . array_sum($groups[$i]) . '<br>number of items: ' . count($groups[$i]) . '<br><br>';
}
?>

答案 1 :(得分:0)

对于小型阵列,蛮力方法可能运行得相当好。

该算法将简单地对数组进行混洗,直到它满足所有约束,或者在最大迭代次数后停止。

define('MAX_ITER',        10000);
define('MIN_CHUNK_SUM',   50);
define('MAX_CHUNK_SIZE',  5);

$chunk = solve(
  array( 1.66, 28.13, 3.37, 2, 12, 88.90, 6.88, 0.57, 1.50 ),
  $i
);

if($chunk === false) {
  printf("No solution found\n");
}
else {
  printf("Found a solution in %d iterations\n", $i);

  foreach($chunk as $n => $c) {
    arsort($c);
    printf("Chunk #%d: SUM = %g with { %s }\n", $n, array_sum($c), implode(", ", $c));
  }
}

function solve($a, &$i) {
  for($i = 0; $i < MAX_ITER; $i++) {
    shuffle($a);
    $chunk = array_chunk($a, MAX_CHUNK_SIZE);

    foreach($chunk as $c) {
      if(array_sum($c) < MIN_CHUNK_SUM) {
        continue 2;
      }
    }
    return $chunk;
  }
  return false;
}

示例输出:

// Found a solution in 4 iterations
// Chunk #0: SUM = 50.51 with { 28.13, 12, 6.88, 2, 1.5 }
// Chunk #1: SUM = 94.5 with { 88.9, 3.37, 1.66, 0.57 }

请注意,arsort()除了在显示解决方案之前标准化解决方案外没有任何其他目的。