Mathematica 745 681 Bytes
Die Grundidee ist, ein gewichtetes Diagramm der möglichen Bewegungen zu erstellen. Gewichte sind die Zeit, die benötigt wird, um von einem Ort zum nächsten zu gelangen. Der Weg mit dem geringsten Gewicht ist der schnellste.
Die Eingabestellen werden in ein Rechteckarray von r x c (Zeilen x Spalten) eingefügt, und dann kommen drei verschiedene Darstellungen ins Spiel: (1) ein Gittergraph von r x c, wobei jeder Scheitelpunkt einer Zelle im Array entspricht. (2) (r c) durch (r c) eine gewichtete Adjazenzmatrix, die Gewichte enthält, die der Zeit entsprechen, die (2, 3 oder 11 Minuten) benötigt, um sich von einer Stelle (im Gitterdiagramm) zu einer anderen zu bewegen, und (3) eine gerichtete gewichteter Adjazenzgraph aus der Matrix.
Das Gitterdiagramm hilft zu bestimmen, welche Zellen (dh welche Eckpunkte) möglicherweise von jedem Eckpunkt aus erreichbar sind - "möglicherweise erreichbar", da eine benachbarte Zelle nicht nur rechts, links, über oder unter einer bestimmten Zelle sein darf. Der Wert muss sich auch innerhalb einer Entfernungseinheit zum Nachbarn befinden (z. B. eine 3 verbindet sich nicht mit einer benachbarten 5 oder einer 1). Wenn Eckpunkta
nicht mit dem Scheitelpunkt verbunden ist, haben b
die Adjazenzmatrixzellen {a, b} und {b, a} den Wert ∞. Dementsprechend weist der gewichtete Nachbarschaftsgraph weder eine Kante von a nach b noch von b nach a auf.
Der gewichtete Adjazenzgraph dient dazu, den Mindestabstand ( GraphDistance
) und den kürzesten Weg zwischen den Eckpunkten zu bestimmen . Der optimale Pfad muss mit 1 beginnen, jeden der Gipfel berühren und zu 1 zurückkehren. In diesem Fall ist "kürzeste Route" nicht unbedingt diejenige mit den wenigsten Zügen. Es ist das mit der kürzesten Gesamtzeit, gemessen in Kantengewichten.
Golf gespielt
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]]
Längere, besser lesbare Form
(*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]]]
Tests
weights["4 5
32445
33434
21153
12343"]
96.
weights@"2 7
6787778
5777679"
75.
weights@"3 4
1132
2221
1230"
51.
Erläuterung
Denken Sie an die Zeilen 2-5 der folgenden Eingabe
"4 5
32445
33434
21153
12343"
als Darstellung eines Arrays mit 4 Zeilen und 5 Spalten:
Dabei entspricht jeder Scheitelpunkt einer Ziffer aus dem Eingabearray: 3 befindet sich bei Scheitelpunkt 1, 2 befindet sich bei Scheitelpunkt 2, 4 befindet sich bei Scheitelpunkt 3, weitere 4 bei Scheitelpunkt 4, 5 bei Scheitelpunkt 5 usw. Der Gittergraph ist nur eine grobe Darstellung Annäherung des Diagramms, das wir anstreben. Es ist ungerichtet. Darüber hinaus sind einige der Kanten nicht verfügbar. (Denken Sie daran: Wir können nicht von einer Position zu einer anderen wechseln, die mehr als 1 Höheneinheit über oder unter der aktuellen liegt.) Mit dem Gitterdiagramm können wir jedoch die Eckpunkte finden, die sich neben einem ausgewählten Eckpunkt befinden. Dies reduziert die Anzahl der Kanten, die wir im ersten Beispiel (ein 4 × 5-Raster) berücksichtigen müssen, von 400 (20 × 20) auf 62 (31 × 2 ist die Anzahl der Kanten im Gitterdiagramm). Im selben Beispiel sind nur 48 der Kanten wirksam. 14 sind nicht.
Die folgende 20 x 20 gewichtete Adjazenzmatrix repräsentiert den Abstand zwischen allen Knotenpaaren aus dem Gitterdiagramm.
Der Schlüsselcode, der über die zuzuweisende Nummer entscheidet, ist unten angegeben.
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}->∞}]
Die Zelle {1,2} enthält - bei einer Indizierung - den Wert 2, da die Verschiebung von Scheitelpunkt 1 zu Scheitelpunkt 2 bergab verläuft. Zelle {2,1} enthält 11, da der Übergang von Scheitelpunkt 2 zu Scheitelpunkt 1 bergauf verläuft. Die 3en in den Zellen {1,6} und {6,1} bedeuten, dass die Bewegung weder nach oben noch nach unten gerichtet ist. Zelle {1,1} enthält ∞, weil sie nicht mit sich selbst verbunden ist.
Das folgende Diagramm zeigt die Struktur, die der obigen Eingabe zugrunde liegt. Die farbigen Pfeile zeigen den optimalen Pfad von Scheitelpunkt 1 zu den Gipfeln (bei 5 und 14) und zurück zu 1. Blaue Pfeile entsprechen Bewegungen auf derselben Ebene (3 Minuten); rote Pfeile bedeuten Aufstieg (11 min) und grüne Pfeile Abstieg (2 min).
Der Pfad von Scheitelpunkt 1 (Zelle {1,1} zu den beiden Gipfeln und zurück zu Scheitelpunkt 1:
3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3
96