Сведения о вопросе

Fhohir

03:07, 6th August, 2020

Теги

Найдите наилучшую комбинацию из заданного множества множеств

Просмотров: 548   Ответов: 7

Скажем, у вас есть груз. Он должен пройти от точки А до точки Б, от точки Б до точки C и, наконец, от точки C до точки D. вам нужно добраться туда за пять дней за наименьшую сумму денег. Есть три возможных грузоотправителя для каждой ноги, каждый со своим собственным различным временем и стоимостью для каждой ноги:

Array
(
    [leg0] => Array
        (
            [UPS] => Array
                (
                    [days] => 1
                    [cost] => 5000
                )

            [FedEx] => Array
                (
                    [days] => 2
                    [cost] => 3000
                )

            [Conway] => Array
                (
                    [days] => 5
                    [cost] => 1000
                )

        )

    [leg1] => Array
        (
            [UPS] => Array
                (
                    [days] => 1
                    [cost] => 3000
                )

            [FedEx] => Array
                (
                    [days] => 2
                    [cost] => 3000
                )

            [Conway] => Array
                (
                    [days] => 3
                    [cost] => 1000
                )

        )

    [leg2] => Array
        (
            [UPS] => Array
                (
                    [days] => 1
                    [cost] => 4000
                )

            [FedEx] => Array
                (
                    [days] => 1
                    [cost] => 3000
                )

            [Conway] => Array
                (
                    [days] => 2
                    [cost] => 5000
                )

        )

)

Как вы собираетесь найти лучшую комбинацию программно?

Моя лучшая попытка до сих пор (третий или четвертый алгоритм) :

  1. Найдите самый длинный грузоотправитель для каждой ноги
  2. Устранить большинство "expensive" один
  3. Найти самый дешевый грузоотправитель для каждой ноги
  4. Рассчитайте общую стоимость & дней
  5. Если дни приемлемы, закончите, иначе, Гото 1

Быстро высмеивается в PHP (обратите внимание, что тестовый массив ниже работает плавно, но если вы попробуете его с тестовым массивом сверху, он не найдет правильную комбинацию):

$shippers["leg1"] = array(
    "UPS"    => array("days" => 1, "cost" => 4000),
    "Conway" => array("days" => 3, "cost" => 3200),
    "FedEx"  => array("days" => 8, "cost" => 1000)
);

$shippers["leg2"] = array(
    "UPS"    => array("days" => 1, "cost" => 3500),
    "Conway" => array("days" => 2, "cost" => 2800),
    "FedEx"  => array("days" => 4, "cost" => 900)
);

$shippers["leg3"] = array(
    "UPS"    => array("days" => 1, "cost" => 3500),
    "Conway" => array("days" => 2, "cost" => 2800),
    "FedEx"  => array("days" => 4, "cost" => 900)
);    

$times = 0;
$totalDays = 9999999;

print "<h1>Shippers to Choose From:</h1><pre>";
print_r($shippers);
print "</pre><br />";

while($totalDays > $maxDays && $times < 500){
            $totalDays = 0;
            $times++;
            $worstShipper = null;
            $longestShippers = null;
            $cheapestShippers = null;

            foreach($shippers as $legName => $leg){
                //find longest shipment for each leg (in terms of days)
                unset($longestShippers[$legName]);
                $longestDays = null;        

                if(count($leg) > 1){
                    foreach($leg as $shipperName => $shipper){
                        if(empty($longestDays) || $shipper["days"] > $longestDays){
                            $longestShippers[$legName]["days"] = $shipper["days"];
                            $longestShippers[$legName]["cost"] = $shipper["cost"];
                            $longestShippers[$legName]["name"] = $shipperName;
                            $longestDays = $shipper["days"];
                        }
                    }           
                }
            }

            foreach($longestShippers as $leg => $shipper){
                $shipper["totalCost"] = $shipper["days"] * $shipper["cost"];

                //print $shipper["totalCost"] . " &lt;?&gt; " . $worstShipper["totalCost"] . ";";

                if(empty($worstShipper) || $shipper["totalCost"] > $worstShipper["totalCost"]){
                    $worstShipper = $shipper;
                    $worstShipperLeg = $leg;
                }
            }

            //print "worst shipper is: shippers[$worstShipperLeg][{$worstShipper['name']}]" . $shippers[$worstShipperLeg][$worstShipper["name"]]["days"];
            unset($shippers[$worstShipperLeg][$worstShipper["name"]]);

            print "<h1>Next:</h1><pre>";
            print_r($shippers);
            print "</pre><br />";

            foreach($shippers as $legName => $leg){
                //find cheapest shipment for each leg (in terms of cost)
                unset($cheapestShippers[$legName]);
                $lowestCost = null;

                foreach($leg as $shipperName => $shipper){
                    if(empty($lowestCost) || $shipper["cost"] < $lowestCost){
                        $cheapestShippers[$legName]["days"] = $shipper["days"];
                        $cheapestShippers[$legName]["cost"] = $shipper["cost"];
                        $cheapestShippers[$legName]["name"] = $shipperName;
                        $lowestCost = $shipper["cost"];
                    }
                }

                //recalculate days and see if we are under max days...
                $totalDays += $cheapestShippers[$legName]['days'];  
            }
            //print "<h2>totalDays: $totalDays</h2>";
        }

        print "<h1>Chosen Shippers:</h1><pre>";
        print_r($cheapestShippers);
        print "</pre>";

Я думаю, что мне, возможно, придется на самом деле сделать что-то вроде того, где я буквально делаю каждую комбинацию по одному (с серией петель) и складываю общее "score" каждого и нахожу лучший....

EDIT: Чтобы уточнить, это не задание "homework" (я не в школе). Это часть моего текущего проекта на работе.

Требования (как всегда) постоянно менялись. Если бы мне дали текущие ограничения в то время, когда я начал работать над этой проблемой, я бы использовал какой-то вариант алгоритма A* (или Dijkstra'S, или shortest path, или simplex, или что-то еще). Но все менялось и менялось, и это привело меня туда, где я сейчас нахожусь.

Поэтому я думаю, что это означает, что мне нужно забыть обо всем дерьме, которое я сделал до этого момента, и просто пойти с тем, что я знаю, что должен идти, что является алгоритмом поиска пути.



  Сведения об ответе

FAriza

03:51, 8th August, 2020

Можно было бы изменить некоторые из алгоритмов кратчайшего пути, например Дийкстры, чтобы взвесить каждый путь по стоимости, но также отслеживать время и перестать идти по определенному пути, если время превышает ваш порог. Нужно найти самое дешевое, что попадет вам под ваш порог таким образом


  Сведения об ответе

nYU

01:30, 13th August, 2020

Похоже, то, что у вас есть, называется a "linear programming problem". Это также звучит как проблема с домашним заданием, без обид.

Классическое решение задачи LP называется "Simplex Method". Погуглите его.

Однако, чтобы использовать этот метод, вы должны правильно сформулировать проблему, чтобы описать свои требования.

Тем не менее, можно перечислить все возможные пути, поскольку у вас есть такой небольшой набор. Однако такая вещь не будет масштабироваться.


  Сведения об ответе

baggs

22:02, 16th August, 2020

Звучит как задание для алгоритма Дейкстры :

Алгоритм Дейкстры, разработанный голландским ученым-компьютерщиком Эдсгером Дейкстрой в 1959 году, 1 -это алгоритм поиска графа, который решает задачу одноисточникового кратчайшего пути для графа с неотрицательными затратами на путь ребра, выводя дерево кратчайшего пути. Этот алгоритм часто используется в маршрутизации.

Есть также детали реализации в статье Википедии.


  Сведения об ответе

LIZA

16:28, 13th August, 2020

Если бы я знал, что мне придется иметь дело только с 5 городами, в заранее определенном порядке, и что между соседними городами есть только 3 маршрута, я бы сделал это грубо. Нет смысла быть элегантным.

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


  Сведения об ответе

davran

16:03, 28th August, 2020

Это проблема рюкзака . Весы - это дни в пути, и прибыль должна быть $5000-стоимость ноги. Устраните все негативные издержки и идите оттуда!


  Сведения об ответе

park

18:08, 17th August, 2020

Как сказал Балтимарк, это в основном проблема линейного программирования. Если бы только коэффициенты для грузоотправителей (1 для включенных, 0 для не включенных) не были (двоичными) целыми числами для каждой ветви, это было бы более легко разрешимо. Теперь вам нужно найти некоторые (двоичные) эвристики целочисленного линейного программирования (ILP), поскольку задача NP-трудная. Смотрите Википедию по целочисленному линейному программированию для ссылок; на моем курсе линейного программирования мы использовали как минимум ветвление и привязку .

На самом деле теперь, когда я думаю об этом, этот частный случай разрешим без фактического ILP, поскольку количество дней не имеет значения, пока оно составляет <= 5. Теперь начните с выбора самого дешевого перевозчика для первого выбора (Conway 5:1000). Далее вы снова выбираете самый дешевый, в результате чего 8 дней и 4000 единиц валюты-это слишком много, поэтому мы прерываем это. Пробуя другие, мы видим, что все они дают дни > 5, поэтому мы возвращаемся к первому выбору и пробуем второй самый дешевый (FedEx 2:3000), а затем ups во втором и fedex в последнем. Это дает нам в общей сложности 4 дня и 9000 единиц валюты.

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

Надеюсь, эта бессвязность немного помогла:).


  Сведения об ответе

VCe znayu

09:00, 13th August, 2020

Я думаю, что алгоритм Дейкстры - это поиск кратчайшего пути.

cmcculloh ищет минимальную стоимость при условии ограничения, что он получает ее там в течение 5 дней.

Так что, просто найдя самый быстрый способ, он не доберется туда дешевле всего, а добравшись туда за самый дешевый, он не доберется туда за необходимое количество времени.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться