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 분)을 나타냅니다.
정점 1 (셀 {1,1}에서 두 개의 정점으로 그리고 다시 정점 1 로의 경로입니다.
3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3
96