Как я могу найти самый дешевый способ в DAG, если у меня ограниченные деньги?

Итак, если у меня есть направленный ациклический граф, где стоимость каждого ребра равна 0 или больше 0, если она больше 0, она будет иметь отрицательный вес (так что вы можете купить ее за 5 долларов, и это сократит ваш путь на -20 например).

Я знаю, что мы можем легко найти кратчайший/самый дешевый путь в DAG, но что, если у нас ограниченные деньги?

Итак, представьте следующую ситуацию:

dag

У нас есть 8 денег. Алгоритм найдет кратчайший путь, равный -10+-3=-13, но он будет стоить 12, а у нас только 8 денег, так что это не вариант. Идеальный путь будет -10+0, который стоит всего 7 денег. Есть ли алгоритм, который я могу использовать для решения этой проблемы?


person Ryper    schedule 07.07.2015    source источник


Ответы (3)


Эта задача относится к категории сложной NP, с сокращением от задача о рюкзаке.

Короткое интуитивное «доказательство»: идея в том, чтобы создать вершину для каждого элемента — вы можете «брать» или «не брать», выбирая вершину со стоимостью или «свободную» вершину. .

Эскиз:

введите здесь описание изображения

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

Более формально:

Для экземпляра рюкзака с weights=w1,w2,w3,...cn и cost=c1,c2,..,cn с некоторым максимальным весом W создайте граф G=(V,E) с

V= { V_i,U_i,W_i | i=0,...n }
E= { (W_i,V_i+1,U_i+1 | i=0,...,n-1} U {(V_i,W_i+1), (U_i,W_i+1) | i=0,...,n-1 }

value(W_i,V_i+1) = c_i+1
money(W_i,V_i+1) = w_i+1
value(W_i,U_i+1) = 0
money(W_i,U_i+1) = 0
money(V_i,W_i+1) = cost(V_i,W_i+1) = money(U_i,W_i+1) = cost(U_i,W_i+1) = 0

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


Возможным псевдополиномиальным решением может быть (с использованием метода динамического программирования) :

D(start,0) = 0
D(v,x) = infinity     x < 0
D(v,x) = min { D(u,x-money(u,v)) + value(u,v) | for each edge (u,v) } U {infinity}

В приведенном выше D(v,x) минимальное расстояние, необходимое для путешествия от начального узла до v, заплатив ровно x денег.

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

Когда закончите, вам нужно найти все значения x от 0 до MAXIMAL_AMOUNT_OF_MONEY_ALLOWED, чтобы найти минимальное значение D(target,x), и это ответ.
Нахождение фактической стоимости выполняется путем повторного отслеживания ваших шагов, как это делается в других решениях динамического программирования.

Вышеуказанная продолжительность работы O(|V|*MAX_MONEY + |E|)

person amit    schedule 07.07.2015
comment
Выглядит хорошо, но я не мог понять фрагмент предложения - и обозначьте стоимость, или проигнорируйте ее, и извлеките из нее ценность со стоимостью, которую вы готовы заплатить за это. Также было бы полезно упомянуть, что D(v, x) — это минимальное расстояние, которое вам нужно пройти, чтобы добраться от начала до v, если у вас изначально есть $x в кармане. Наконец, я думаю, что в повторении должно быть D(u,x-money(u,v)) + value(u,v), поскольку значения (веса), по-видимому, отрицательны. - person j_random_hacker; 07.07.2015
comment
@j_random_hacker Спасибо за отзыв, отредактировано. Не стесняйтесь уточнить немного больше, если считаете это необходимым (поскольку мне нужно отвести сына на физиотерапию, и я вернусь только через несколько часов). - person amit; 07.07.2015
comment
да, я почти уверен, что мне нужно использовать вариант задачи о рюкзаке, но я думаю, что ваше решение намного сложнее этой проблемы, и я не вижу, где оно решит следующую проблему: Итак, представьте себе график с 5 вершинами я сохраняю только ребра между i и вершиной i+1. i57.tinypic.com/30w1itk.jpg Вот матрица, правила просты, мы можем выбрать только одно ребро из вершины A в B , поэтому мы можем выбрать только одно ребро из столбца. Итак, что бы сделал алгоритм, если бы у нас был предел веса (= Деньги) в 13 следующих комментариев: - person Ryper; 07.07.2015
comment
([строка][столбец]) (думаю, я упрощаю эту матрицу) 1) он выберет [0][1], [1][1], [3][1], [0][ 0] это общий вес 10, а значение будет 17, но мы выбрали больше ребер из одного столбца, что неприемлемо 2) будет выбрано [0][0],[2][1], что будет вес 11 , и значение будет 12, это правильно. Но как алгоритм узнает, что он может выбрать только один из одного столбца, я не могу этого представить, есть идеи? - person Ryper; 07.07.2015
comment
@Ryper Это решение в значительной степени представляет собой прямую модификацию рюкзака для решения этой проблемы. Если вы согласны, что это рюкзак, то нет более простого (эффективного) решения, чем это. Алгоритм никогда не выбирает более одного ребра, ведущего к каждой вершине, он выбирает не более одного ребра (или ни одного, если нет допустимого решения), что гарантирует min{..} - выбор только одного ребра. - person amit; 07.07.2015
comment
@amit, что вы имеете в виду, выбирая создание графика для каждого элемента ?? я думаю, я понимаю, знаю, как работает рюкзак, мне нужно только это - person Ryper; 07.07.2015
comment
@Ryper Это создание вершины для каждого элемента, опечатка. Но обратите внимание, что это НЕ то, что вы ищете. Первая часть ответа объясняет, почему задача является NP-сложной, и показывает, что вы можете преобразовать рюкзак в свою задачу. Вы ищете вторую часть ответа, где рекурсивная формула D(v,x) - так вы решаете свою задачу за псевдополиномиальное время. - person amit; 07.07.2015
comment
Давайте продолжим обсуждение в чате. - person Ryper; 07.07.2015

Используйте алгоритм флуда. Правила:
В каждом посещенном узле обновить массив путей и их цен.
Освободить массив, когда посещенный узел больше не нужен.
Всегда удалять пути с ценой > денег.
Начать флуд в на исходном узле.
Завершить наводнение в целевом узле, когда все входящие ребра будут заполнены.
Следовать за наводнением, используя исходящие ребра, когда все входящие ребра будут заполнены.
В конце выберите путь с самой высокой ценой в целевом узле. узел.

person Pavel Gatnar    schedule 07.07.2015
comment
@НикласБ. да, но только в худшем случае - person Pavel Gatnar; 07.07.2015
comment
@PavelGatnar Вовсе нет, средний случай - это экспоненциальное количество путей. - person amit; 07.07.2015

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

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

Предполагая, что у вас есть какая-то функция для проверки следующего ребра на пути (и если у вас ее нет или нет в этом формате, просто адаптируйте ее к тому, что у вас есть)...

// accepts the edge you are checking, max cost, and the sum weight and cost so far to this point
// returns float array {sum cost, sum weight), or infinity if cost is exceeded
void checkNextStep(Edge* edge, float maxCost, float* sumWeight, float* sumCost)
{
    if(*sumCost + edge->cost > maxCost)
    {
        *sumWeight = INFINITY;
        *sumCost += edge->cost;
    }
    *sumWeight += edge->weight;
    *sumCost += edge->cost;
}

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

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

person Loduwijk    schedule 07.07.2015
comment
Этот подход неоптимален (не даст вам лучшего решения). Вы не можете изменить кратчайший путь, чтобы получить оптимальный ответ на эту проблему, по крайней мере, не просто, и предполагая, что P!=NP - person amit; 07.07.2015
comment
Этот подход дает задающему вопрос решение, о котором просили, что означает, что вы получите лучшее решение. Спрашивающий определил лучшее решение как возвращение кратчайшего пути, стоимость которого не превышает порогового значения. Вы не можете просто сказать, что не можете... не подкрепив это. То, что я предоставил, будет работать, если я что-то не упускаю из виду. Если в нем ошибка, то, пожалуйста, объясните, где ошибка. С того места, где я сижу, я вижу совершенно хороший ответ (возможно, лучший; это спорно, в зависимости от того, как вам нравится форматировать ваши ответы), который игнорируется. - person Loduwijk; 08.07.2015
comment
Я поддержал это. В своем ответе я доказал, что эта проблема NP-Hard. Это означает, что для него не существует известного полиномиального решения, и большинство считает, что его нет. - person amit; 08.07.2015
comment
Вот еще одно доказательство для вас: Аскер заявил, что кратчайший путь можно найти (предполагая уже существующий код или, по крайней мере, доступный алгоритм). Аскер заявил, что существует вторичная стоимость (деньги), и пути, которые превышают порог вторичной стоимости, должны быть отклонены (здесь нет необходимости в оптимизации, просто отклоняйте определенные пути). Я дал рекомендацию по изменению кода спрашивающего (который может существовать, а может и не существовать; эта часть не была указана, насколько я помню), и, насколько я могу судить, это работает. КЭД. - person Loduwijk; 08.07.2015
comment
Я только что понял кое-что. Когда вы говорите о неоптимальном и лучшем решении, вы имеете в виду, что мое предложение не даст ответ, который хочет спрашивающий, или вы имеете в виду, что оно не обеспечивает наилучшее решение в том смысле, что это не лучшее алгоритмическое решение для использования найти ответ, который хочет спрашивающий? Утверждение может быть воспринято в любом случае, и они разные, поэтому я могу говорить не о том же, что и вы. - person Loduwijk; 08.07.2015
comment
Я имею в виду, что он может вернуть более длинный путь, чем самый короткий, который может быть достигнут с заданным бюджетом. Вы знаете, что такое задачи NP-Hard? (Это нормально, если вы этого не сделаете, но вы должны прочитать о них, прежде чем отклонять аргумент, который их касается) - person amit; 08.07.2015
comment
Доказательство в вашем комментарии не работает, потому что его кратчайший путь работает на множестве ребер без ограничений. Добавление ограничения делает весь алгоритм поиска кратчайшего пути неверным. Проблема в том, что у вас может быть 10 долларов, а сейчас вы видите ярлык, который стоит 9 долларов. С вашим подходом вы можете принять это, но это отключит все ярлыки в будущем, которые стоят 2 доллара каждый, поэтому, если каждый ярлык дает вам одинаковое значение (скажем, -1), вы бы предпочли взять 5 * 2 доллара. ярлыки, а не 1*9$. Но жадный подход приведет к сокращению в 9 долларов. - person amit; 08.07.2015
comment
Я помню, как проходил это в колледже, поэтому я знаю основную идею, да. Что касается вашего последнего комментария, то, как я читаю вопрос спрашивающего, я не вижу в этом требования. Если вы хотите сделать такие оптимизации, то это хорошо. Я не думаю, что это было частью вопроса, как указано, но я полагаю, вы могли бы прочитать это таким образом. Я читал, что у меня есть кратчайший путь, но я хочу, чтобы он игнорировался, если он выше стоимости, а не я хочу, чтобы рассматривался лучший путь с учетом денег. Тем не менее, я не отрицаю того, что вы делаете, так что это спорно, я трачу наше время и откланяюсь сейчас. - person Loduwijk; 08.07.2015