Những người khác so sánh điều này với Vấn đề Người bán hàng Đi du lịch có lẽ đã không đọc kỹ câu hỏi của bạn. Trong TSP, mục tiêu là tìm chu trình ngắn nhất truy cập tất cả các đỉnh (chu trình Hamilton) - nó tương ứng với việc mọi nút có nhãn 'phải đi qua'.
Trong trường hợp của bạn, cho rằng bạn chỉ có khoảng một tá nhãn 'phải vượt qua', và cho rằng 12! khá nhỏ (479001600), bạn chỉ có thể thử tất cả các hoán vị của chỉ các nút 'phải vượt qua' và xem đường dẫn ngắn nhất từ 'bắt đầu' đến 'kết thúc' truy cập các nút 'phải vượt qua' theo thứ tự đó - nó sẽ đơn giản là nối các đường đi ngắn nhất giữa hai nút liên tiếp trong danh sách đó.
Nói cách khác, trước tiên hãy tìm khoảng cách ngắn nhất giữa mỗi cặp đỉnh (bạn có thể sử dụng thuật toán Dijkstra hoặc các thuật toán khác, nhưng với số lượng nhỏ đó (100 nút), ngay cả thuật toán Floyd-Warshall mã đơn giản nhất cũng sẽ chạy đúng lúc). Sau đó, khi bạn có cái này trong bảng, hãy thử tất cả các hoán vị của các nút 'phải bỏ qua' của bạn và phần còn lại.
Một cái gì đó như thế này:
//Precomputation: Find all pairs shortest paths, e.g. using Floyd-Warshall
n = number of nodes
for i=1 to n: for j=1 to n: d[i][j]=INF
for k=1 to n:
for i=1 to n:
for j=1 to n:
d[i][j] = min(d[i][j], d[i][k] + d[k][j])
//That *really* gives the shortest distance between every pair of nodes! :-)
//Now try all permutations
shortest = INF
for each permutation a[1],a[2],...a[k] of the 'mustpass' nodes:
shortest = min(shortest, d['start'][a[1]]+d[a[1]][a[2]]+...+d[a[k]]['end'])
print shortest
(Tất nhiên đó không phải là mã thực, và nếu bạn muốn đường dẫn thực, bạn sẽ phải theo dõi xem hoán vị nào cho khoảng cách ngắn nhất và cũng là đường đi ngắn nhất của tất cả các cặp, nhưng bạn có ý tưởng.)
Nó sẽ chạy trong ít nhất vài giây trên bất kỳ ngôn ngữ hợp lý nào :)
[Nếu bạn có n nút và k nút 'phải bỏ qua', thời gian chạy của nó là O (n 3 ) cho phần Floyd-Warshall và O (k! N ) cho tất cả các phần hoán vị và 100 ^ 3 + (12!) (100) thực tế là đậu phộng trừ khi bạn có một số ràng buộc thực sự hạn chế.]