Tôi có biểu đồ có trọng số, không có trọng số âm và tôi muốn tìm đường dẫn từ nút này sang nút khác, cố gắng giảm thiểu chi phí cho một bước . Tôi không cần phải giảm thiểu tổng chi phí của chuyến đi (ví dụ: Dijkstra làm) nhưng chi phí mỗi bước trung bình. Tuy nhiên, tôi có một ràng buộc: K, số lượng nút tối đa trong đường dẫn.Vấn đề tuyến đường trong biểu đồ: giảm chi phí cạnh trung bình thay vì tổng chi phí
Vì vậy, ví dụ như để đi từ A đến J có lẽ Dijkstra sẽ tìm thấy con đường này (giữa ngoặc trọng lượng)
A (4) D (6) J -> total cost: 10
và các thuật toán tôi cần, thiết K = 10, sẽ tìm thấy một cái gì đó giống như
A (1) B (2) C (2) D (1) E (3) F (2) G (1) H (3) J -> total cost: 15
Có bất kỳ thuật toán nổi tiếng nào cho vấn đề này không?
Xin cảm ơn trước.
Eugenio
Chỉnh sửa câu trả lời cho templatetypedef. Một số câu hỏi:
1) Thực tế là có thể xảy ra chu kỳ nhiều lần để giảm tốc độ trung bình không tốt cho vấn đề của tôi: có lẽ tôi đã đề cập đến nó nhưng tôi không muốn truy cập cùng một nút nhiều hơn một lần
2) Có thể khai thác thực tế là tôi không có trọng số âm?
3) Khi bạn nói O (kE) bạn có nghĩa là cho toàn bộ thuật toán hoặc chỉ cho phần bổ sung? Hãy thực hiện việc thực hiện đơn giản này trong C trong đó n = số nút e = số cạnh, d là một vector với khoảng cách, vector pa với tiền thân và cạnh cấu trúc (u, v, w) ghi nhớ các cạnh trong biểu đồ
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;
}
Tôi không chắc mình nên sửa đổi mã theo câu trả lời của bạn như thế nào; để đưa vào xem xét mức trung bình thay vì tổng chi phí nên điều này là đủ?
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++;
}
Nhưng dù sao tôi không biết cân nhắc giới hạn K cùng một lúc ... Cảm ơn bạn đã giúp bạn.
Sửa Kể từ khi tôi có thể đủ khả năng một số lỗi Tôi đang suy nghĩ về giải pháp Naif này:
- precompute tất cả các con đường ngắn nhất và ghi nhớ trong Một
- precompute tất cả các đường đi ngắn nhất trên đồ thị biến đổi , nơi tôi cắt các cạnh trên một trọng lượng nhất định và ghi nhớ chúng trong B
Khi tôi cần một con đường, tôi nhìn vào A, ví dụ: từ x đến y, đây là đường dẫn x-> z-> y sau đó cho mỗi bước tôi nhìn vào B, vì vậy đối với x> z Tôi thấy nếu có kết nối trong B, nếu không tôi giữ x> z nếu không Tôi điền vào đường dẫn x> z với đường phụ được cung cấp bởi B, có thể giống như x-> j-> h-> z; sau đó tôi làm tương tự cho z-> y. Mỗi lần tôi cũng sẽ kiểm tra xem tôi có thêm một đường dẫn tuần hoàn hay không.
Có lẽ tôi sẽ nhận được một số đường dẫn kỳ lạ nhưng nó có thể hoạt động trong hầu hết các trường hợp. Nếu tôi mở rộng giải pháp đang thử với các "ngưỡng cắt" khác nhau, có lẽ tôi cũng có thể gần với sự tôn trọng giới hạn K.
Bạn phải cẩn thận với điều này vì vòng lặp Bellman-Ford theo dõi các đường dẫn có độ dài * lên đến * k, vì vậy việc tìm đường dẫn chi phí tối thiểu sau lần lặp k Bellman-Ford không nhất thiết phải trả lời đúng. Xem giải pháp của tôi về cách sửa lỗi này. – templatetypedef
Xin chào @Hypuk cảm ơn câu trả lời, tôi không chắc liệu tôi có xây dựng câu hỏi hay không. Tại thời điểm này tôi thực sự sử dụng Bellman-Ford nhưng đường dẫn tôi nhận được quá ngắn và chi phí của mỗi cạnh quá cao ... Tôi muốn có một chuyến đi dài nhất (nhiều cạnh hơn, chi phí cho mỗi cạnh), nhưng nếu Tôi chỉ cần thiết lập "sử dụng tối đa K cạnh" như quy tắc tôi sẽ nhận được cùng một kết quả tôi nhận được ngay bây giờ, phải không? – Eugenio
Xin lỗi tôi đang sử dụng http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm chứ không phải Bellman-Ford – Eugenio