PHP найти самую дешевую перестановку

#php #algorithm #math #search

#php #алгоритм #математика #Поиск

Вопрос:

У меня есть несколько продуктов, у всех которых есть размеры, и мне нужно найти самую дешевую конфигурацию, которая соответствует минимально необходимому размеру.

Например, Джону нужно минимум 10 литров хранилища — это может быть больше, но не меньше.

Есть варианты 2L, 3L, 5L, 8L и 10L (но это может измениться).

В качестве примера, может быть дешевле получить:

  • контейнер объемом 1×10 л ИЛИ
  • контейнеры объемом 2×5 л Или
  • 1x2L, 1x3L и 1x5L ИЛИ
  • 4x3L (этот занимает более 10 литров, но все еще возможно, что он будет дешевле)

До сих пор я пытался выполнять цикл снова и снова до 4 раз (потому что обычно максимальное требование будет составлять 40 литров), но в некоторых случаях у меня заканчивается память, и это не кажется самым эффективным способом сделать это.

 
// Size is in mL

$available_containers = [
[
  'id' => 22700,
  'price' => 1190,
  'size' => 2000,
],
[
  'id' => 22701,
  'price' => 1245,
  'size' => 3000,
],
[
  'id' => 22702,
  'price' => 1415,
  'size' => 4000,
],
[
  'id' => 22715,
  'price' => 12300,
  'size' => 5000,
],
[
  'id' => 22706,
  'price' => 1740,
  'size' => 5000,
],
[
  'id' => 22703,
  'price' => 1510,
  'size' => 5000,
],
[
  'id' => 22707,
  'price' => 1790,
  'size' => 6000,
],
[
  'id' => 22704,
  'price' => 1770,
  'size' => 6000,
],
[
  'id' => 22708,
  'price' => 2215,
  'size' => 7000,
],
[
  'id' => 22705,
  'price' => 2195,
  'size' => 8200,
],
[
  'id' => 22709,
  'price' => 2660,
  'size' => 8200,
],
[
  'id' => 22710,
  'price' => 2799,
  'size' => 10000,
],
[
  'id' => 22711,
  'price' => 2910,
  'size' => 12500,
],
[
  'id' => 22712,
  'price' => 3260,
  'size' => 15000,
],
[
  'id' => 22713,
  'price' => 4130,
  'size' => 20000,
],
[
  'id' => 22714,
  'price' => 3770,
  'size' => 27000,
]
];

$required_size = 8; // Can change.
$container_install = 5;

foreach ( $available_containers as $v ){
  foreach ( $available_containers as $v2 ){
    foreach ($available_containers as $v3 ) {
      foreach ( $available_containers as $v4 ){

        $all_configs = [
          [
            'size' => $v['size'],
            'configuration' => [ $v['size'] ],
            'price' => $v['price'],
          ],
          [
            'size' => $v['size']   $v2['size'],
            'configuration' => [ $v['size'], $v2['size'] ],
            'price' => $v['price']   $v2['price']   $container_install,
          ],
          [
            'size' => $v['size']   $v2['size']   $v3['size'],
            'configuration' => [ $v['size'], $v2['size'], $v3['size'] ],
            'price' => $v['price']   $v2['price']   $v3['price']   $container_install   $container_install,
          ],
          [
            'size' => $v['size']   $v2['size']   $v3['size']   $v4['size'],
            'configuration' => [ $v['size'], $v2['size'], $v3['size'], $v4['size'] ],
            'price' => $v['price']   $v2['price']   $v3['price']   $v4['price']   $container_install   $container_install   $container_install,
          ],
        ];


        foreach ( $all_configs as $c ){
          if ( $c['size'] >= $required_size ){
            $configuration[] = array(
              'configuration' => $c['configuration'],
              'size' => $c['size'],
              'price' => $c['price'],
            );
          }
        }
      }
    }
  }
}


// Sort by price.
$sorted_configs = array_sort($configuration, 'price', SORT_ASC); // This function simply sorts all permutations by price
  

Комментарии:

1. n x n x n n x n не является хорошей сложностью. вы можете попробовать эту рекурсивную функцию docstore.mik.ua/orelly/webprog/pcook/ch04_26.htm

2. Что вам нужно сделать, это выполнить цикл один раз, возможно, с циклом while, затем использовать деление, чтобы получить количество раз, которое оно входит в каждый (в порядке от наибольшего к наименьшему), Вычесть это значение и сделать это снова. Каждый раз уменьшая исходное значение.

3. Похоже, это скорее вопрос для codereview.stackexchange.com

4. Спасибо @JosuaMarcelChrisano — я посмотрю.

5. @ArtisticPhoenix — Я не математический гений — просто программист, ха-ха. Можете ли вы пояснить на примере?

Ответ №1:

Ну, есть некоторые моменты, которые могут сделать эти циклы легкими. Эта проблема должна быть решена с помощью подхода «разделяй и властвуй».

  1. Создайте подмассив, потому что вам не нужен весь массив, только новый подмассив от 1L до 10L.
  2. Вложенный массив должен быть отсортирован по цене, от наименьшей к высоте.
  3. Тогда и только тогда, когда самая низкая цена, которая представлена в первом индексе, может быть куплена только один раз, break цикл.
  4. В противном случае у вас должен быть список, который принимает выходные данные, когда вы уже выполняете цикл.