특정 노드를 방문하는 그래프에서 최단 경로 찾기


82

약 100 개의 노드와 약 200 개의 에지가있는 무 방향 그래프가 있습니다. 하나의 노드는 '시작', 하나는 '종료'이며, 'mustpass'라는 레이블이 붙은 약 12 ​​개가 있습니다.

'시작'에서 시작하고 '끝'에서 끝나고 모든 '반드시 통과'노드 (순서에 관계없이)를 통과 하는이 그래프를 통해 최단 경로를 찾아야합니다 .

( http://3e.org/local/maize-graph.png / http://3e.org/local/maize-graph.dot.txt 는 해당 그래프입니다. 펜실베니아 주 랭커스터의 옥수수 미로를 나타냅니다)

답변:


77

이것을 Traveling Salesman Problem과 비교하는 다른 사람들은 아마 당신의 질문을주의 깊게 읽지 않았을 것입니다. TSP에서 목표는 모든 정점 을 방문하는 가장 짧은주기 (해밀턴주기)를 찾는 것입니다. 이는 모든 노드가 'mustpass'라는 레이블 을 갖는 것에 해당합니다 .

귀하의 경우에는 'mustpass'라는 레이블이 붙은 약 12 ​​개만 가지고 있고 그 12 개가 주어졌습니다! 다소 작습니다 (479001600). 'mustpass'노드의 모든 순열 만 시도하고 'mustpass'노드를 순서대로 방문하는 'start'에서 'end'까지의 최단 경로를 살펴볼 수 있습니다. 해당 목록에있는 두 개의 연속 노드 사이의 최단 경로 연결입니다.

즉, 먼저 각 정점 쌍 사이의 최단 거리를 찾으십시오 (Dijkstra의 알고리즘 또는 다른 알고리즘을 사용할 수 있지만이 작은 수 (100 개 노드)를 사용하면 가장 간단한 코드화 Floyd-Warshall 알고리즘 도 시간 내에 실행됩니다). 그런 다음 테이블에 이것을 가지고 있으면 'mustpass'노드의 모든 순열을 시도하고 나머지는 시도하십시오.

이 같은:

//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

(물론 실제 코드가 아니며 실제 경로를 원한다면 가장 짧은 거리를 제공하는 순열과 모든 쌍의 최단 경로가 무엇인지 추적해야하지만 아이디어를 얻을 수 있습니다.)

합리적인 언어에서 최대 몇 초 안에 실행됩니다. :)
[n 개의 노드와 k 개의 'mustpass'노드가있는 경우 실행 시간은 Floyd-Warshall 부분의 경우 O (n 3 )이고 O (k! n ) 모든 순열 부분에 대해, 100 ^ 3 + (12!) (100)은 실제로 제한적인 제약이없는 한 사실상 땅콩입니다.]


5
입력 크기가 작기 때문에 대답에 동의합니다. 그러나 나는 이것이 TSP의 경우라는 다른 사람들의 주장을 왜 거부하는지에 관심이 있습니다. 내가 이해하는 방식으로 모든 필수 통과 노드를 추출하여 하위 그래프를 만드는 데 사용할 수 있습니다. 하위 그래프의 노드 간 간선에는 원래 그래프의 APSP 솔루션에 해당하는 가중치가 있습니다. 그러면 질문이 하위 그래프에서 TSP의 사례가되지 않습니까? 귀하의 솔루션은 해당 문제에 대한 무차별 대입 솔루션 인 것으로 보입니다 (괜찮습니다).
maditya

6
@maditya : 첫째, (Steven A Lowe의 다른 답변에 대한 의견을 인용하기 위해) "TSP는 어렵습니다, bwahahaha"와 같은 답변은 해결해야 할 실제 문제가있는 사람, 특히 매우 쉽게 해결할 수있는 답변이 아니라는 데 동의하시기 바랍니다. 지난 수십 년 동안 모든 컴퓨터에서 해결되었습니다. 둘째, 이것은 사소한 이유 (다른 입력 형식)로 인해 TSP와 동일하지 않습니다. 포함 된 TSP의 작은 인스턴스는 입력 크기 N이 아닌 작은 그래프 용입니다. 따라서 NP- 완전성은 'mustpass'노드 수에 따라 다릅니다. 점근 적으로 있습니다 : 항상 12이거나 O (log N)이면 NP-complete가 아닙니다.
ShreevatsaR 2013

1
결과가 경로인지 확실하지 않습니다. 에서 갈 필요 상상 ac통해 b. 이것은 최단 경로 때문일 수 bac에지를 공유한다. 이 경우 가장자리가 두 번 반복됩니다. 사이클을 생성하지 않으려면 두 경로 중 하나가 최적 경로보다 나빠 야합니다.
Spak

1
@PietroSaccardi 질문의 설명에서 목표는 단순히 모든 노드를 통과하는 가장 짧은 "방법"을 찾는 것이며, 일부 에지가 반복되면 괜찮을 수 있습니다. 즉,“경로”가 느슨한 의미로 사용되고 있습니다. 사실, 반복되는 모서리가 허용되지 않으면 답이 없을 수도 있습니다 (예를 들어 B를 통과하면서 A에서 C로 이동하도록 요청받는 그래프 B-A-C를 고려하십시오. 반복하지 않을 방법이 없습니다. B—A 모서리).
ShreevatsaR

Floyd-Warshall 알고리즘은 여기서 올바르게 구현되지 않았습니다. 배열의 모든 셀이로 초기화되기 때문에 INFd[i][j] = min(d[i][j], d[i][k] + d[k][j])d[i][j] = min(INF, INF + INF)이고 모든 셀은 항상 INF. 이 배열을 그래프의 가장자리 길이로 채우려면 단계를 추가해야합니다.
Stef

24

Djikstra의 알고리즘 을 실행 하여 모든 중요 노드 (start, end, must-pass) 사이의 최단 경로를 찾은 다음, depth-first traversal은 모든 노드 start에 닿는 결과 하위 그래프를 통해 최단 경로를 알려줍니다. . mustpasses ... 끝


이것은 선택한 솔루션보다 더 효율적일 가능성이있는 것 같습니다. 나는 당신이 그것을 조금 더 구체화했다면 더 높은 점수를 얻었을 것입니다. 나는 먼저 모든 쌍 사이의 최단 경로가 모든 필수 노드 사이의 경로를 보장하는지 여부를 생각해야했습니다.
galactikuh

경로가 가장자리를 반복하지 않아야하는 경우 이것이 작동하지 않는다고 생각합니다.
tuket

1
코드 출현 24 일의 예에서 깊이 우선 순회는 어떻게 최단 경로를 찾을 수 있습니까? adventofcode.com/2016/day/24
Erwin Rooijakkers

15

이것은 두 가지 문제입니다. Steven Lowe는 이것을 지적했지만 문제의 후반부에 대해서는 충분히 존중하지 않았습니다.

먼저 모든 중요 노드 (start, end, mustpass) 사이의 최단 경로를 찾아야합니다. 이러한 경로가 발견되면 단순화 된 그래프를 구성 할 수 있습니다. 여기서 새 그래프의 각 에지는 원래 그래프의 한 중요 노드에서 다른 노드로의 경로입니다. 여기에서 최단 경로를 찾는 데 사용할 수있는 경로 찾기 알고리즘이 많이 있습니다.

하지만이 새 그래프가 있으면 출장 영업 사원 문제가 발생합니다 (거의 ... 시작 지점으로 돌아갈 필요가 없습니다). 위에서 언급 한 이와 관련된 모든 게시물이 적용됩니다.


14

사실 당신이 올린 문제는 여행하는 세일즈맨과 비슷하지만 단순한 길 찾기 문제에 더 가깝다고 생각합니다. 모든 노드를 방문 할 필요없이 가능한 최단 시간 (거리)에 특정 노드 집합을 방문하기 만하면됩니다.

그 이유는 여행하는 세일즈맨 문제와 달리 옥수수 미로는지도의 한 지점에서 다른 지점으로 이동하기 위해 다른 노드를 통과 할 필요없이 직접 이동할 수 없기 때문입니다.

실제로 고려할 기술로 A * 길 찾기를 권장합니다. 다른 노드에 직접 액세스 할 수있는 노드와 특정 노드의 각 홉 "비용"을 결정하여이를 설정합니다. 이 경우 노드가 비교적 가까운 간격으로 보이기 때문에 각 "홉"의 비용이 동일 할 수 있습니다. A *는이 정보를 사용하여 두 지점 간의 최저 비용 경로를 찾을 수 있습니다. A 지점에서 B 지점으로 이동하여 약 12 ​​명 사이에 방문해야하므로 길 찾기를 사용하는 무차별 대입 접근 방식도 전혀 문제가되지 않습니다.

고려할 대안입니다. 여행하는 세일즈맨 문제와 매우 비슷해 보이며 읽어보기에 좋은 문서이지만 자세히 살펴보면 그 문제가 지나치게 복잡하다는 것을 알 수 있습니다. ^ _ ^ 이전에 이런 일을 해본 적이있는 비디오 게임 프로그래머의 마음에서 나온 것입니다.


2
+1-이것은 '여행하는 세일 맨 문제는 어렵습니다, bwahahaha'보다 훨씬 더 나은 대답입니다
Steven A. Lowe

5

Andrew Top은 올바른 아이디어를 가지고 있습니다.

1) Djikstra의 알고리즘 2) 일부 TSP 휴리스틱.

Lin-Kernighan 휴리스틱을 권장합니다. NP Complete 문제로 가장 잘 알려진 것 중 하나입니다. 기억해야 할 또 다른 사항은 2 단계 이후에 그래프를 다시 확장 한 후 확장 된 경로에 루프가있을 수 있으므로이를 단락시켜야한다는 것입니다 (경로를 따라있는 정점의 정도를 확인).

이 솔루션이 최적에 비해 얼마나 좋은지 실제로는 잘 모르겠습니다. 단락과 관련된 병리학 적 사례가있을 수 있습니다. 결국,이 문제는 Steiner Tree : http://en.wikipedia.org/wiki/Steiner_tree 와 매우 비슷해 보이며 그래프를 축소하고 예를 들어 Kruskal을 실행하는 것만으로는 Steiner Tree를 근사화 할 수 없습니다.


5

입니다 하지 원래의 질문이 노드가 한 번만 방문하는 것을 반드시 통과를 필요로하지 않기 때문에 TSP 문제와 NP-어려운 일이 아니다. 이것은 Dijkstra의 알고리즘을 통해 모든 필수 통과 노드 사이의 최단 경로 목록을 컴파일 한 후 무차별 대입에 대한 대답을 훨씬 간단하게 만듭니다. 더 나은 방법이있을 수 있지만 간단한 방법은 단순히 이진 트리를 거꾸로 작업하는 것입니다. 노드 목록 [start, a, b, c, end]를 상상해보십시오. 간단한 거리 [start-> a-> b-> c-> end]를 더합니다. 이것은 이길 새로운 목표 거리입니다. 이제 [start-> a-> c-> b-> end]를 시도하고 그게 더 낫다면 대상으로 설정하십시오 (그리고 노드의 패턴에서 나왔음을 기억하십시오). 순열에 대해 거꾸로 작업하십시오.

  • [시작-> a-> b-> c-> 끝]
  • [시작-> a-> c-> b-> 끝]
  • [시작-> b-> a-> c-> 끝]
  • [시작-> b-> c-> a-> 끝]
  • [시작-> c-> a-> b-> 끝]
  • [시작-> c-> b-> a-> 끝]

그중 하나가 가장 짧습니다.

( '여러 번 방문한'노드는 어디에 있습니까? 최단 경로 초기화 단계에서 숨겨져 있습니다. a와 b 사이의 최단 경로에는 c 또는 끝 점이 포함될 수 있습니다. 신경 쓸 필요가 없습니다. )


최단 경로라는 조건으로 한 번만 방문하면됩니다.
Aziuth

허. 나는 몇 분 전에 확실히 확신했지만 네, 맞습니다. 분명히 여러 가지가있는 나무에는 없습니다. 그러나 문제를 완전히 연결된 mustpass 노드 만 포함하고 원래 그래프에서 가장 짧은 경로의 거리를 가진 노드를 포함하는 새로운 그래프로 문제를 추상화하면 TSP에 도달합니다. 그래서, 그것이 NP 하드가 아니라고 확신합니까? 일반적인 문제에서 mustpass 노드의 양은 전체 노드의 양에 따라 달라지며, 예를 들어 전체가 mustpass의 다항식이면 NP-hardness를 얻습니다.
Aziuth

예를 들어 a-> b에서 오는 경로는 c를 통과 할 수 있습니다. 따라서 어떤 brnach도 다른 것을 막지 못합니다. 그것은 단지 순열입니다.
bjorke 2016 년

예? 그러나 "총 노드는 mustpass 노드의 다항식"과 같이 mustpass 노드의 양이 전체 노드의 양과 연결되어 있다고 가정하면 순열은 O (n!)입니다. 무차별 대입으로 TSP를 해결했습니다.
Aziuth

2

노드와 에지의 양이 상대적으로 유한하다는 점을 고려하면 가능한 모든 경로를 계산하고 가장 짧은 경로를 선택할 수 있습니다.

일반적으로 이것은 여행하는 세일즈맨 문제로 알려져 있으며 사용하는 알고리즘에 관계없이 비 결정적 다항식 런타임이 있습니다.

http://en.wikipedia.org/wiki/Traveling_salesman_problem


1

질문 은 어떤 순서로든 반드시 통과해야합니다 . 반드시 통과 노드의 정의 된 순서에 대한 솔루션을 찾으려고 노력하고 있습니다. 내 대답을 찾았지만 StackOverflow에 대한 질문이 없었기 때문에 최대한 많은 사람들이 혜택을 누릴 수 있도록 여기에 게시하고 있습니다.

주문 또는 필수 통과가 정의 된 경우 dijkstra의 알고리즘을 여러 번 실행할 수 있습니다. 예를 들어 s통과에서 k1, k2k3(각 순서대로)에서 중지 해야한다고 가정 해 보겠습니다 e. 그런 다음 각 연속 노드 쌍 사이에서 dijkstra의 알고리즘을 실행할 수 있습니다. 비용경로 에 의해 제공 될 것이다 :

dijkstras(s, k1) + dijkstras(k1, k2) + dijkstras(k2, k3) + dijkstras(k3, 3)


0

12 개의 '필수 방문'노드에서 무차별 대입을 사용하는 것은 어떻습니까? 12 개 노드의 가능한 모든 조합을 충분히 쉽게 처리 할 수 ​​있으며이를 통해이를 처리 할 수있는 최적의 회로를 사용할 수 있습니다.

이제 문제는 시작 노드에서 회로까지의 최적 경로를 찾는 중 하나로 단순화됩니다. 그런 다음이를 다룰 때까지이 경로를 따라 간 다음 그에서 끝까지의 경로를 찾습니다.

최종 경로는 다음으로 구성됩니다.

시작-> 회로 경로 *-> 노드를 방문해야하는 회로-> 끝 경로 *-> 끝

이렇게 *로 표시된 경로를 찾으십시오.

시작 노드에서 회로의 모든 지점까지 A * 검색을 수행합니다. 이들 각각에 대해 회로의 다음 및 이전 노드에서 끝까지 A * 검색을 수행합니다 (양쪽 방향으로 순환을 따라갈 수 있기 때문입니다). 검색 경로가 많고 비용이 가장 낮은 경로를 선택할 수 있습니다.

검색을 캐싱하여 최적화 할 여지는 많이 있지만 이것이 좋은 솔루션을 생성 할 것이라고 생각합니다.

하지만 검색에서 반드시 방문해야하는 회로를 떠나는 것이 포함될 수 있기 때문에 최적의 솔루션을 찾는 데는 거의 없습니다.


0

어디에도 언급되지 않은 한 가지는 경로에서 동일한 정점을 두 번 이상 방문해도 괜찮은지 여부입니다. 여기에있는 대부분의 답변은 동일한 가장자리를 여러 번 방문해도 좋다고 가정하지만, 질문 (경로가 동일한 꼭지점을 두 번 이상 방문해서는 안됩니다!)은 동일한 꼭지점을 두 번 방문하는 것은 괜찮지 않다는 것입니다 .

따라서 무차별 대입 방식이 여전히 적용되지만 경로의 각 하위 집합을 계산하려고 할 때 이미 사용 된 정점을 제거해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.