문제

Im 찾는 알고리즘에 사용되는 레이싱 게임 만들기.맵/수준의/트랙에는 임의로 생성된 그래서 나는 찾아야 할 두 개의 위치를 시작하고,목표를 사용하는 대부분의지도입니다.

  • 알고리즘을 작품 안에 두 차원 공간
  • 각 지점에서,할 수만 통과하는 다음 포인트는 네 방향으로;up,down,left,right
  • 포인트 수 차단되거나 nonblocked 만 nonblocked 인할 수 있습 과

에 관한 거리의 계산되지 않도록 해야 한다"새 경로"의 부족을 위해 더 나은 단어입니다.사이의 경로 A,B 이상이어야하는 경우가 있는 벽(또는 다른 차단 지역)니다.

Im 지에서 시작,주석은 매우 환영하고 제안 솔루션은 기본에서 의사의 코드입니다.

편집: 오른쪽.후을 통해 보고 gs 코드 나는 그것을 또 다른 기회.대신 python,나는 이 시간 그것을 썼에서는 C++.하지만 아직 후에도,읽기에 Dijkstras 알고리즘, 이, floodfillHosam 알리스 솔루션, 에,나는 실패의 자리를 모든 중요한 차이입니다.나의 코드가 여전히 작동,하지만 당신과 같이 이야기를 실행합니다.전체 소스에 pastie.만 흥미로운 선(나)이트라 변 자체 라인에서 78-118.

하지만 속도가 아니라 주요 문제 여기에.내가 정말 도움을 주셔서 감사합니다면 누군가는 것을 지적하는 차이점에서 알고리즘이 있습니다.

  • 에 Hosam 알리스 알고리즘,유일한 차이는 검사에서 국경을 대신 모든 노드?
  • 에 Dijkstras 추적을 유지하고 덮어쓰기는 거리에 걸어 있지만 floodfill 지만 그것에 대해?
도움이 되었습니까?

해결책

맵이 직사각형이라고 가정하면 모든 테두리 지점을 루프하고 홍수 채우기를 시작하여 시작점에서 가장 먼 지점을 찾을 수 있습니다.

bestSolution = { start: (0,0), end: (0,0), distance: 0 };
for each point p on the border
    flood-fill all points in the map to find the most distant point
    if newDistance > bestSolution.distance
        bestSolution = { p, distantP, newDistance }
    end if
end loop

나는 이것이있을 것이라고 생각한다 O(n^2). 내가 착각하지 않으면, 그것은입니다 (L+W) * 2 * (L*W) * 4, 어디 L 길이와 W 지도의 너비입니다. (L+W) * 2 주변의 테두리 지점의 수를 나타냅니다. (L*W) 포인트 수입니다 4 홍수 충전이 최대 4 배 (모든 방향에서)에 접근 할 것이라고 가정합니다. 부터 n 포인트 수와 동일하며 이는 다음과 같습니다. (L + W) * 8 * n, 그보다 나은 것입니다 O(n2). (지도가 정사각형이면 순서는 O(16n1.5).)

업데이트: 주석에 따라,지도는 미로에 더 가깝기 때문에 (처음에 생각했던 것처럼 간단한 장애물이있는 것보다) 위의 동일한 논리를 만들 수는 있지만지도의 모든 지점을 확인할 수 있습니다 (테두리의 지점과 반대로. ). 이것은 순서대로되어야합니다 O(4n2), FW와 Dijkstra보다 여전히 낫습니다.

메모: 홍수 충전 모든 정점은 4 개의 경계를 통해 직접 연결되어 있기 때문에이 문제에 더 적합합니다. 맵의 폭이 넓은 첫 번째 횡단은 비교적 빠르게 결과를 얻을 수 있습니다 ( O(n)). 나는 4 개의 이웃 각각의 홍수 채우기에서 각 지점을 점검 할 수 있다고 가정합니다. 따라서 위의 공식의 계수가 있습니다.

Update 2: 이 알고리즘과 관련하여받은 모든 긍정적 인 피드백에 감사드립니다. @georg에게 특별한 감사를드립니다 그의 리뷰.

추신 : 모든 의견이나 수정 사항을 환영합니다.

다른 팁

Floyd-Warshall 또는 간단한 알고리즘에 대한 질문에 대한 후속 조치 Hosam Aly:

두 방법을 모두 사용할 수있는 테스트 프로그램을 만들었습니다. 파일입니다.

모든 테스트 사례에서 Floyd-Warshall은 큰 크기가 느려졌습니다. 아마도 이것은 아마도이 알고리즘이이를 달성하는 데 도움이되는 매우 제한된 모서리 때문일 것입니다.

이 시대는 필드가 4 배가 될 때마다 10 개의 필드 중 3 개가 장애물이었습니다.

Size         Hosam Aly      Floyd-Warshall
(10x10)      0m0.002s       0m0.007s     
(20x20)      0m0.009s       0m0.307s
(40x40)      0m0.166s       0m22.052s
(80x80)      0m2.753s       -
(160x160)    0m48.028s      -

Hosam Aly의 시간은 2 차 인 것처럼 보이므로 해당 알고리즘을 사용하는 것이 좋습니다. 또한 Floyd-Warshall의 메모리 소비는 n입니다2, 분명히 필요 이상. Floyd-Warshall이 왜 그렇게 느린 지 알고 있으면 의견을 남기 거나이 게시물을 편집하십시오.

추신 : 나는 오랫동안 C 또는 C ++를 작성하지 않았기 때문에 너무 많은 실수를하지 않았기를 바랍니다.

Floyd-Warshall 알고리즘을 추천하는 원래 게시물을 삭제했습니다. :(

GS는 현실적인 벤치 마크를 수행했습니다 그리고 FW는 전형적인 맵 크기에 대한 Hosam Aly의 "Flood Fill"알고리즘보다 실질적으로 느리게 진행됩니다! 따라서 FW는 멋진 알고리즘이고 밀도가 높은 그래프의 DijkStra보다 훨씬 빠르더라도 OP의 문제에 대해 더 이상 권장 할 수 없습니다. 여기에는 매우 드문 그래프가 포함됩니다 (각 정점에는 4 개의 가장자리가 있습니다).

기록을 위해 :

  • 효율적인 구현 Dijkstra의 알고리즘 E 모서리와 V 정점이있는 그래프에 O (Elog V) 시간이 걸립니다.
  • Hosam Aly의 "홍수 채우기"는 a 폭 너비 첫 번째 검색,, 이것은 O (v)입니다. 이것은 정점이 거리 추정치를 수정할 수없는 Dijkstra 알고리즘의 특별한 경우로 생각할 수 있습니다.
  • 그만큼 Floyd-Warshall 알고리즘 O (v^3) 시간이 걸리고 코딩하기가 매우 쉽고 여전히 빽빽한 그래프에서 가장 빠릅니다 (정점이 일반적으로 다른 많은 정점에 연결된 그래프). 그러나 그것은입니다 올바른 선택이 아닙니다 매우 희소 그래프가 포함 된 OP의 작업의 경우.

당신이 원하는 것이 그래프 직경. 상당히 좋고 계산하기 쉬운 근사치는 임의의 지점을 선택하고 가장 먼 지점을 찾은 다음 거기에서 가장 먼 지점을 찾는 것입니다. 이 마지막 두 지점은 최대 분리에 가깝습니다.

직사각형 미로의 경우, 이것은 두 개의 홍수 충전물이 당신에게 아주 좋은 시작과 끝점을 얻어야 함을 의미합니다.

라이문드 자이델은 간단한 방법을 사용 행렬의 곱셈을 계산하는 모든 쌍 거리 매트릭스에 가중되지 않은,무향 그래프(는 정확하게 당신이 원하는 무엇)의 첫 번째 섹션에서 자신의 종이 에 모든 쌍-가장 짧은 경로 문제에 가중되지 않은 무방향을 그래프 [pdf].

입력이 인접성 매트릭스와 출력은 모든 쌍 가장 짧은 경로 거리 matrix.실행 시간은 오(M(n)*로그(n))n 점 M(n)은 실행 시간의 행렬의 곱셈 알고리즘이 있습니다.

종이 제공한 방법을 컴퓨팅의 실제 경로(같은 실행 시간)는 경우에 당신이 필요합니다.

자이델의 알고리즘은 시원하기 때문에 실행 시간은 독립적인 수의 가장자리에,하지만 우리는 실제로 걱정하지 않기 때문에 여기 우리의 그래프는 있습니다.그러나,이것은 여전히 좋은 선택이 될(에도 불구하고 약간 더보다 n^2-실행 시간)하려면 모든 쌍 거리 매트릭스,그리고 이것을 수도 있습 쉽게 구현 및 디버그상 floodfill 에 미로입니다.

여기에는 의사 코드:

Let A be the nxn (0-1) adjacency matrix of an unweighted, undirected graph, G

All-Pairs-Distances(A)
    Z = A * A
    Let B be the nxn matrix s.t. b_ij = 1 iff i != j and (a_ij = 1 or z_ij > 0)
    if b_ij = 1 for all i != j return 2B - A //base case
    T = All-Pairs-Distances(B)
    X = T * A
    Let D be the nxn matrix s.t. d_ij = 2t_ij if x_ij >= t_ij * degree(j), otherwise d_ij = 2t_ij - 1
    return D

을 얻을 한 쌍의 포인트는 가장 큰 거리가 우리가 돌아 argmax_ij(d_ij)

완제 python 형의트라 솔루션하는 문제입니다.코드 얻은 조금 오래도록 게시 다른 곳에 그것: http://refactormycode.com/codes/717-dijkstra-to-find-two-points-furthest-away-from-each-other

에서 크기 설정,그것은 약 1.5 초 동안 실행하는 알고리즘에 대한 하나의 노드입니다.그것을 실행에 대한 모든 노드에 몇 분 정도 소요될 수 있습니다.

지 작동하는 것이지만,그것은 항상 표시되고 좌측상 bottomright 모퉁이로 가장 긴 경로;58 타일이 있습니다.는 물론은 진정한 때,당신은 장애물이 있습니다.그러나 심지어 몇 가지를 추가 임의로 배치된 것,여전히 프로그램을 발견한 한 가장 긴 것입니다.어쩌면 그것은 아직도 진정한 하드를 테스트하지 않고 더 진보된 모양입니다.

그러나 어쩌면 그것은 적어도 내 ambition.

자, "Hosam의 알고리즘"은 노드에서 사전 선택이있는 폭이 넓은 첫 번째 검색입니다. 가장자리에 무게가 없기 때문에 Dijkstra의 알고리즘은 여기에 적용해서는 안됩니다.

가장자리의 무게가 다르면 많은 옵션 (대체 경로)을 열어 모든 단계마다 확인해야하므로 차이는 중요합니다. 이것은 알고리즘을 더 복잡하게 만듭니다. 너비의 첫 번째 검색을 사용하면 각 노드의 가장 짧은 경로를 찾는 Garantuees가있는 방식으로 모든 가장자리를 한 번 탐색합니다. 즉, 가장자리를 찾을 수있는 순서대로 탐색함으로써.

따라서 기본적으로 차이점은 Dijkstra가 '백 트랙'해야하며 가장 짧은 경로를 따르기 위해 이전에 탐색 한 가장자리를 살펴 보는 반면, 폭은 첫 번째 검색은 항상 가장 짧은 경로를 따르고 있음을 알고 있습니다.

또한 미로에서 외부 테두리의 지점은 가장 긴 경로의 일부로 보장되지 않습니다. 예를 들어, 거대한 나선형 모양의 미로가 있지만 외부 끝이 중간으로 돌아 가면 나선의 핵심과 나선 끝에 다른 하나를 가질 수 있습니다. 중간에!

따라서이 작업을 수행하는 좋은 방법은 모든 지점에서 폭을 먼저 검색하지만 검색 후 시작점을 제거하는 것입니다 (이미 모든 경로를 알고있는 모든 경로를 알고 있음). 너비의 복잡성은 먼저 o (n)이며, 여기서 n = | v |+| e |. 우리는 V의 모든 노드에 대해 이것을 한 번 수행하므로 O (n^2)가됩니다.

당신의 설명은 나에게 a처럼 들립니다 미로 라우팅 문제. 확인하십시오 이 알고리즘. VLSI 디자인의 장소 및 라우트 문제에 관한 책이 도움이 될 수 있습니다. Sherwani의 "VLSI 물리 디자인 자동화를위한 알고리즘" 좋고 당신은 찾을 수 있습니다 SAIT 및 YouSSEF의 VLSI 물리 디자인 자동화 유용하고 (그리고 Google 버전에서 저렴한 ...)

객체 (포인트)가 자주 움직이지 않으면 O (n^3) 시간보다 훨씬 짧은 계산을 수행 할 수 있습니다.

공간을 큰 그리드로 분해하고 그리드 간 거리를 사전 계산하는 것입니다. 그런 다음 대부분의 먼 그리드를 차지하는 포인트 쌍을 선택하는 것은 간단한 테이블 조회의 문제입니다. 평균적인 경우에는 작은 개체 세트 만 확인해야합니다.

이 솔루션은 거리 메트릭이 연속적 인 경우 작동합니다. 따라서 예를 들어지도에 많은 장벽이 있다면 (미로에서와 같이)이 방법이 실패 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top