최고봉 경험 : 모든 봉우리를 빠르게 방문


22

고도가 숫자로 표시되는 x 맵의 한 지점 (0,0)에 서 있습니다 .HW

1132
2221
1230    # H = 3, W = 4

나는 모든 피크의 전망을 경험하고 싶습니다.이 경우 고도가있는 지역입니다 3. 그러나 언덕을 오르는 것은 쉬운 일이 아니며 시간이 부족합니다.

도전

문제는 모든 봉우리를 방문하고 다시 올 수있는 가장 빠른 길을 찾는 것입니다.

최단 프로그램이 이깁니다.

입력

  • H, W-지도의 높이 및 너비 (정수) (선택 사항, 목록 / 튜플 또는 두 개의 개별 정수 입력일 수 있음)
  • 편리한 형식 (2D 목록, 줄 바꿈으로 구분 된 문자열 등) H으로 W숫자 세트 ( 0- 9) 로 제공되는 맵

산출

  • 모든 피크를 방문하고 시작 지점으로 돌아 오는 데 가장 짧은 시간 (정수)

정황

  • 주어진 영역의 고도는에서 0까지 의 숫자로 표시 됩니다 9.
  • "피크"는 고도가 가장 높은 지역에 의해 정의됩니다.
  • 경로는 왼쪽 상단 (0,0) 영역 에서 시작하고 끝나야 합니다.
  • 현재 영역에 인접한 영역으로 만 이동할 수 있으며 대각선으로 이동할 수 없습니다.
    • 고도에 변화가 없으면 한 지역에서 다른 지역으로 이동하는 데 3 분이 걸립니다 .
    • 올라가려면 11 분이 걸립니다 . 즉, 한 영역에서 다른 영역으로 정확하게 이동하는 것입니다 1.
    • 내려 가려면 2 분이 걸립니다 . 즉, 한 영역에서 다른 영역으로 정확하게 이동하는 것입니다 1.
    • 현재 위치보다 더 1높거나 낮은 영역으로 이동할 수 없습니다 . (고도 지역에서 고도가 높은 1인접 지역으로 갈 수는 없습니다 . 3)
  • 모든 피크로의 경로가 보장됩니다
  • 최대 피크 수는 15입니다.

시료

입력

4 5
32445
33434
21153
12343

산출

96

설명

왼쪽 상단에서 시작합니다 3. 당신은이 개 방문해야 5에 위치의 (0,4)등을 (3,3)하고 돌아올 3에서 (0,0)가능한 짧은 시간이다.

3  2  4->4->5
V     ^
3->3->4  3  4

2  1  1  5  3

1  2  3  4  3    # 3 + 3 + 11 + 3 + 3 + 11 = 34 minutes to visit 1st peak


3  2  4  4  5
            V
3  3  4  3  4
            V
2  1  1  5  3
         ^  V
1  2  3  4<-3    # 2 + 2 + 3 + 11 + 11 = 29 minutes to visit 2nd


3  2  4  4  5
^            
3  3  4  3  4
^            
2  1  1  5  3
^        V   
1<-2<-3<-4  3    # 2 + 2 + 2 + 2 + 11 + 11 + 3 = 33 minutes to come back

# 34 + 29 + 33 = 96 minutes total is the answer

입력

2 7
6787778
5777679

산출

75

9
PPCG에 오신 것을 환영합니다. 첫번째 질문입니다. 답변을 채점하려면 객관적인 승리 기준이 있어야하므로 코드 골프 질문으로 변경하는 것이 좋습니다.
Deusovi

4
추천 해 주셔서 감사합니다, 나는 도움말 센터의 규칙을 읽고 질문 편집
cozyconemotel

타이틀이 개선되면 도전 과제가 더 많은 인기를 얻게 될 것입니다. 아마도 "산 등반 도전".
DavidC

1
cosyconemotel, 나는 당신의 도전에 대한 더 짧고, 아마도 더 매력적인 타이틀을 제안했습니다. 원한다면 언제든지 원래대로 다시 변경하십시오. (제출 후 245
번의 조회수가있었습니다

@DavidC 전적으로 동의합니다. 편집 해 주셔서 감사합니다.
cozyconemotel

답변:


5

Mathematica 745 681 바이트

기본 아이디어는 가능한 이동에 대한 가중치 그래프를 만드는 것입니다. 가중치는 한 장소에서 다음 장소로 이동하는 데 걸리는 시간입니다. 무게가 가장 적은 경로가 가장 빠릅니다.

입력 자릿수는 r x c (행별 열) 사각형 배열에 배치되고 다음 세 가지 고유 한 표현이 나타납니다. (1) r x c 그리드 그래프. 각 정점이 배열의 셀에 해당합니다. (2) (r c) x (r c) 가중 인접 행렬은 그리드 그래프에서 한 위치에서 다른 위치로 이동하는 데 걸리는 시간 (2, 3 또는 11 분)에 해당하는 가중치를 보유하며, , 매트릭스로부터 구성된 가중 인접 그래프.

그리드 그래프는 인접 셀이 주어진 셀의 오른쪽, 왼쪽, 위 또는 아래에 있어야하므로 각 정점에서 도달 할 수있는 셀 (즉, 어떤 정점)을 결정하는 데 도움이됩니다. 또한 값은 이웃과 1 단위 거리 내에 있어야합니다 (예 : 3은 이웃 5 또는 1에 연결되지 않음). 정점 a이 정점 에 연결되어 있지 않으면 b인접 행렬 셀 {a, b} 및 {b, a}의 값은 ∞입니다. 따라서 가중 인접 그래프는 a에서 b로, b에서 a 로의 가장자리가 없습니다.

가중 인접 그래프는 GraphDistance모든 정점 사이 의 최소 ​​거리 ( )와 최단 경로 를 결정하는 데 사용 됩니다. 최적의 경로는 1로 시작하고 각 피크를 터치 한 다음 1로 돌아와야합니다.이 경우 "가장 짧은 경로"가 움직임이 가장 적은 경로 일 필요는 없습니다. 에지 가중치로 측정 된 전체 시간이 가장 짧은 것입니다.


골프

o=Sequence;v[a_<->b_,z_]:=(m_~u~q_:={Quotient[m-1,q[[2]]]+1,1+Mod[m-1, q[[2]]]};j=z[[o@@u[a,i=Dimensions@z]]];k=z[[o@@u[b,i]]];Which[j==k,{{a,b}->3,{b,a}->3},j==k-1,{{a,b}->11,{b,a}->2},j==k+1,{{a,b}->2,{b,a}->11},2<4,{{a,b}->∞, {b, a}->∞}]);w@e_:=Module[{d,x,l,y},x=Map[ToExpression,Characters/@Drop[StringSplit@e,2],{2}];d_~l~c_:=d[[2]](c[[1]]-1)+c[[2]];g_~y~p_:=(Min[Plus@@(GraphDistance[g,#,#2]&@@@#)&/@(Partition[#,2,1]&/@({1,o@@#,1}&/@Permutations@p))]);y[WeightedAdjacencyGraph[ReplacePart[ConstantArray[∞,{t=Times@@(d=Dimensions@x),t}],Flatten[#~v~x &/@Union@Flatten[EdgeList[GridGraph@Reverse@d,#<->_]&/@Range@(Times@@d),1],1]]], l[Dimensions@x, #] & /@ Position[x, Max@x]]

더 길고 읽기 쉬운 양식

(*determines a weight (number of minutes) to go from vertex a to b and from b to a*)
weight[a_ <-> b_, dat_]:= 
  Module[{cellA,cellB,dim,valA,valB,vertexToCell},

  (*Convert graph vertex index to cell location*)
  vertexToCell[m_,dimen_]:={Quotient[m-1,dim[[2]]]+1,1+Mod[m-1,dimen[[2]]]};
     dim=Dimensions[dat];
     cellA = vertexToCell[a,dim];
     cellB = vertexToCell[b,dim];
     valA=dat[[Sequence@@cellA]];
     valB=dat[[Sequence@@cellB]];
     Which[
       valA==valB,{{a,b}-> 3,{b,a}-> 3},
       valA==valB-1,{{a,b}-> 11,{b,a}-> 2},
       valA==valB+1,{{a,b}-> 2,{b,a}-> 11},
       2<4,{{a,b}->∞,{b,a}->∞}]];

(* weights[] determines the edge weights (times to get from one position to the next), makes a graph and infers the shortest distance 
from vertex 1 to each peak and back.  It tries out all permutations of peaks and 
selects the shortest one. Finally, it returns the length (in minutes) of the shortest trip. *)

weights[str_]:=
  Module[{d,dat,neighbors,cellToVertex,peaks,z,gd},
  dat=Map[ToExpression,Characters/@Drop[StringSplit[str],2],{2}];
  cellToVertex[dim_,cell_]:=dim[[2]] (cell[[1]]-1)+cell[[2]];
  peaks[dat_]:= cellToVertex[Dimensions[dat],#]&/@Position[dat,peak =Max[dat]];

     (* to which cells should each cell be compared? neighbors[] is a function defined within weights[]. It returns a graph, g, from which graph distances will be derived in the function gd[] *)
  neighbors[dim_]:=
  Union@Flatten[EdgeList[GridGraph[Reverse@dim],#<->_]&/@Range@(Times@@dim),1];
    d=Dimensions[dat];
    m=ReplacePart[ConstantArray[∞,{t=Times@@d,t}], 
     (*substitutions=*)
    Flatten[weight[#,dat]&/@neighbors[d],1]];
    g=WeightedAdjacencyGraph[m,VertexLabels->"Name",ImageSize->Full,GraphLayout->"SpringEmbedding"];

    (* finds shortest path.  gd[] is also defined within weights[] *)
  gd[g3_,ps_]:=
    Module[{lists,pairs},
    pairs=Partition[#,2,1]&/@({1,Sequence@@#,1}&/@Permutations@ps);
    Min[Plus@@(GraphDistance[g3,#,#2]&@@@#)&/@pairs]]; 

  gd[g,peaks[dat]]]

테스트

weights["4 5
 32445
 33434
 21153
 12343"]

96.


weights@"2 7
 6787778
 5777679"

75.


weights@"3 4
 1132
 2221
 1230"

51.


설명

다음 입력의 2-5 행을 생각하십시오.

"4 5
 32445
 33434
 21153
 12343"

4 개의 행과 5 개의 열이있는 배열을 나타냅니다.

그리드 그래프

여기서 각 정점은 입력 배열의 숫자에 해당합니다. 3은 정점 1에, 2는 정점 2에, 4는 정점 3에, 다른 4는 정점 4에, 5는 정점 5에 등입니다. 그리드 그래프는 거칠기 만합니다. 우리가 목표로하는 그래프의 근사치. 방향이 지정되지 않았습니다. 또한 일부 가장자리를 사용할 수 없습니다. (기억하십시오 : 현재 위치 위나 아래로 1 높이 이상의 다른 위치로 이동할 수는 없습니다.) 그리드 그래프를 사용하면 선택한 정점 옆에있는 정점을 쉽게 찾을 수 있습니다. 이렇게하면 첫 번째 예 (4 x 5 그리드)에서 고려해야 할 에지 수가 400 (20 * 20)에서 62 (31 * 2는 그리드 그래프의 에지 수)로 줄어 듭니다. 동일한 예에서, 48 개의 에지 만이 작동하고; 14는 아닙니다.

다음 20 x 20 가중 인접 행렬은 그리드 그래프에서 모든 정점 쌍 사이의 거리를 나타냅니다.

할당 할 번호를 결정하는 키 코드는 다음과 같습니다.

Which[
      valA==valB,{{a,b}-> 3,{b,a}-> 3},
      valA==valB-1,{{a,b}-> 11,{b,a}-> 2},
      valA==valB+1,{{a,b}-> 2,{b,a}-> 11},
      2<4,{{a,b}->∞,{b,a}->∞}]

1- 인덱싱의 셀 {1,2}에는 정점 1에서 정점 2 로의 이동이 내리막이기 때문에 값 2가 포함됩니다. 정점 2에서 정점 1 로의 이동이 오르막이므로 {2,1} 셀에 11이 들어 있습니다. 셀 {1,6} 및 {6,1}의 3은 움직임이 위 또는 아래가 아님을 나타냅니다. 셀 {1,1}은 (는) 자체에 연결되어 있지 않기 때문에 ∞를 포함합니다.

무게

다음 그래프는 위 입력의 기본 구조를 보여줍니다. 색상이 지정된 화살표는 정점 1에서 피크 (5 및 14) 및 다시 1까지의 최적 경로를 나타냅니다. 파란색 화살표는 동일한 수준 (3 분)에서의 이동에 해당합니다. 빨간색 화살표는 상승 (11 분)을 의미하고 녹색 화살표는 하강 (2 분)을 나타냅니다.

graph2

정점 1 (셀 {1,1}에서 두 개의 정점으로 그리고 다시 정점 1 로의 경로입니다.

3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3

96


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