У меня есть взвешенный график, нет отрицательных весов, и я хотел бы найти путь от одного node к другому, пытаясь минимизировать затраты на один шаг. Мне не нужно сводить к минимуму общую стоимость поездки (как, например, Дейкстра), но и среднюю ступенчатую стоимость. Однако у меня есть ограничение: K, максимальное количество узлов в пути.
Так, например, чтобы перейти от A к J, может быть, Дейкстра найдет этот путь (между скобкой весом)
A (4) D (6) J -> total cost: 10
и необходимый мне алгоритм, установив K = 10, найдет что-то вроде
A (1) B (2) C (2) D (1) E (3) F (2) G (1) H (3) J -> total cost: 15
Есть ли какой-либо известный алгоритм для этой проблемы?
Спасибо заранее.
Евгенио
Изменить как ответ на templatetypedef. Некоторые вопросы:
1) Тот факт, что может случиться, что цикл несколько раз, чтобы снизить средний показатель, не очень хорош для моей проблемы: возможно, я должен был упомянуть об этом, но я не хочу посещать один и тот же node более одного раза
2) Можно ли использовать тот факт, что у меня нет отрицательных весов?
3) Когда вы сказали O (kE), что вы имели в виду весь алгоритм или только для дополнительной части?
Возьмем эту простую реализацию в C, где n = число узлов e = число ребер, d - вектор с расстояниями, вектор pa с предшественником и ребрами структуры (u, v, w) запоминают ребра в графики
for (i = 0; i < n; ++i)
d[i] = INFINITY;
d[s] = 0;
for (i = 0; i < n - 1; ++i)
for (j = 0; j < e; ++j)
if (d[edges[j].u] + edges[j].w < d[edges[j].v]){
d[edges[j].v] = d[edges[j].u] + edges[j].w;
p[edges[j].v] = u;
}
Я не уверен, как мне изменить код в соответствии с вашим ответом; принимать во внимание среднее значение вместо общей стоимости, если этого достаточно?
for (i = 0; i < n; ++i)
d[i] = INFINITY;
d[s] = 0;
for (i = 0; i < n - 1; ++i)
steps = 0;
for (j = 0; j < e; ++j)
if ( (d[edges[j].u]+ edges[j].w)/(steps+1) < d[edges[j].v]/steps){
d[edges[j].v] = d[edges[j].u] + edges[j].w;
p[edges[j].v] = u;
steps++;
}
Но в любом случае я не знаю, как принимать во внимание предел K в то же время... Еще раз заблаговременно за вашу помощь.
Edit Поскольку я могу позволить себе некоторые ошибки, я думаю об этом решении naif:
- прекомпите все кратчайшие пути и запомните в A
- прекомпутеровать все кратчайшие пути на модифицированном графике, где я режу края по определенному весу и запоминаю их в B
Когда мне нужен путь, я смотрю в A, например. от x до y это путь x- > z- > у то для каждого шага я смотрю в B, поэтому для x > z я вижу, есть ли соединение в B, если не хранить x > z, в противном случае я заполняю путь x > z подпутью, предоставленной B, которая может быть чем-то вроде x- > j- > h- > г; то я делаю то же самое для z- > y. Каждый раз, когда я также проверю, добавляю ли я циклический путь.
Возможно, у меня появятся какие-то странные пути, но он может работать в большинстве случаев. Если я продолжу решение, пытаясь использовать разные "пороговые значения", возможно, я также могу быть близким к уважению K constrain.