2010-02-05 4 views
2

Я изучил алгоритм динамического программирования, чтобы найти «самый дешевый» путь от A до B. Каждый дополнительный путь имеет связанную стоимость.Самый дешевый алгоритм пути

Каждый угол рассчитывается с использованием
D(i,j).value = min((D(i-1,j).value + D(i,j).x), (D(i,j-1).value + D(i,j).y))
где х и у являются затраты на пути в левой части узла и ниже узла.

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

Любые предложения?

http://www.freeimagehosting.net/uploads/f6e0884a2d.png

ответ

2

Подход динамического программирования, который вы описываете, называется DAG shortest path. Он работает только с ориентированными ациклическими графами (то есть с графиками без циклов). Его асимптотическим временем выполнения является O (V + E) (где V и E - количество вершин и ребер соответственно), что быстрее алгоритма Дейкстры.

Я не уверен, но вы спрашиваете, как вычислить количество путей, длина которых равна кратчайшему пути?

Вы можете сделать это, сохранив информацию предшественника при вычислении длины кратчайшего пути. Когда вы переходите к узлу j, храните все пары (i, j) таким образом, что переход от i в j является частью кратчайшего пути. Один из способов реализовать это - добавить два поля: D (x, y) .optimalUp и D (x, y) .optimalRight (тип данных boolean), указывая, если вы получите оптимальное решение, если вы ввели (x, y), перейдя вверх или вправо, соответственно. Например, установите для D (x, y) .optimalUp значение true, если перейти от (x, y-1) к самому дешевому пути.

Затем вы можете сделать второй проход, чтобы подсчитать количество самых дешевых путей, используя динамическое программирование. Добавьте еще одно поле, скажем, D (x, y) .count (integer), который имеет самое большое количество способов перехода от A к (x, y) самым дешевым способом. Существует два способа достижения (x, y): Via (x-1, y) и (x, y-1). Счет (x, y-1) должен быть добавлен только к счету (x, y), если можно достичь самого дешевого пути к (x, y), пройдя через (x, y-1). Тот же принцип справедлив для (x-1, y).

тогда мы получаем повторение:

D(x,y).count = 
    D(x,y).optimalUp ? D(x,y-1).count : 0 
    + D(x,y).optimalDown ? D(x-1,y).count : 0 

(?. Есть условный оператор в C/C++/Java)

Судя по вашей картине, кажется, ваш график представляет собой сетку. Остерегайтесь того, что движение только вверх или вправо не должно приводить к кратчайшему пути. На приведенном ниже графике кратчайший путь от A до B равен 8, но вы не можете достичь более 12, если вы идете только вправо и вверх.

x -1-- x -1-- B 
|  |  | 
1  9  9 
|  |  | 
x -1-- x -1-- x 
|  |  | 
9  9  1 
|  |  | 
A -1-- x -1-- x 

Поскольку это обозначено как домашнее задание, на данный момент я не буду предоставлять более подробную информацию, чем это. Тем не менее это должно быть подталкивание в правильном направлении (если я правильно понял вашу проблему). Не стесняйтесь задавать дополнительные вопросы.

+0

Привет, Вы правильно поняли вопрос, хотя я забыл упомянуть, что вы можете только идите направо и вверх. Я не понял, что должен содержать ваш список предшественников. Кроме того, вы упомянули, используя алгоритм динамического программирования, чтобы подсчитать количество путей с длиной, равной кратчайшему пути, и это именно то, что мне трудно понять, как это сделать. Любое разъяснение/помощь будут оценены. – Meir

+0

Добавлено более подробное объяснение того, как рассчитать количество путей. –

0

ЗАКАНЧИВАТЬ хилклаймбинг и A-звезда алгоритмы на википедии.

0

A * является лучшим первым и, вероятно, будет работать очень хорошо для вас.

+0

A * лучше всего подходит для отображения трансверсалей, где некоторые узлы блокируются, а большинство узлов имеют общую стоимость. Вот хорошая ссылка: http://www.policyalmanac.org/games/aStarTutorial.htm –

8

Вы ищете Dijkstra's algorithm. Это алгоритм поиска графа, который решает проблему кратчайшего пути с одним источником для графика с неотрицательными затратами на краевые пути, создавая кратчайшее дерево путей.

+0

Как вы думаете, это самый простой способ сделать что-то? – Meir

+0

Это классика. Существует огромное количество алгоритмов построения диаграмм, но вы должны знать о Дийкстре, если вы смотрите на такие вещи. – Joe

+0

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

0

Попробуйте найти алгоритмы «кратчайшего пути», но есть улов.

Многие поиски кратчайших путей используют расчетное расстояние до цели как эвристику, которая часто должна удовлетворять определенным условиям. A *, например, использует функцию оценки расстояния до цели и гарантированно найдет кратчайший путь, если он никогда не недооценивает расстояние до цели. Поскольку вы ищете путь с минимальными произвольными затратами, у вас не будет такой эвристики, который легко доступен. Кроме того, вы знаете длину пути, поэтому алгоритмы, такие как итерационное углубление, не будут полезны.

Любой детерминированный алгоритм, такой как Dijkstra's algorithm, должен работать нормально.

1

Похоже, вы работаете с графиком, где узлы являются точками на 2D-сетке, и каждый узел имеет направленный край к узлу над ним, а другой - к узлу справа.

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

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

number_paths(i,j)=number_of_paths(i-1,j)+number_of_paths(i,j-1) 

т.е. число путей из любого узла является суммой, что из приведенных выше и справа узлов. (Это исключает базовые случаи, когда текущий узел является пунктом назначения и где узел назначения недоступен для текущего узла.)

Единственное, что нужно, это изменить это, чтобы считать только самые дорогие пути. Теперь мы уже знаем, что самый дешевый путь имеет некоторую стоимость X. Мы можем использовать его для увеличения нашего повторения, чтобы он учитывал только самый дешевый путь. На стартовом узле мы знаем, что стоимость оставшегося пути равна X. От любого из соседних узлов к стартовому узлу (т. Е. Из узлов непосредственно выше и справа от него), следовательно, стоимость Xe, где e - стоимость края между этими узлами. Это правило применяется к любому узлу, где известны затраты на достижение текущего узла. Таким образом, мы знаем, что мы прошли самый дешевый путь, когда мы достигли целевого узла, а значение этого узла равно 0 (т. Е. Мы вычтем все затраты на ребра, которые образуют самый дешевый путь).

Таким образом, мы можем просто увеличить нашу повторяемость, чтобы мы сохранили 3 значения вместо 2, координаты и оставшуюся стоимость пути (по существу, превращаясь в ту же задачу для 3D-графика, где 3-е измерение является стоимостью). Начальный узел имеет вид (x_start,y_start,cost), целевой узел имеет вид (x_end,y_end,0). Наше повторение будет выглядеть так:

paths(x,y,cost_left)= 
       0   if x_end,y_end is unreachable from x,y or cost_left<0 
       1   if x==X-end and y==y_end and cost_left==0 
       paths(x-1,y,cost_left-edge(x,y,x-1,y))+paths(x,y-1,cost_left-edge(x,y,x,u-1)) otherwise 

Сложность алгоритма должны быть O (п м C), где п и т являются размерами сетки и C является стоимостью самого дешевого пути.

Смежные вопросы