Mathematica 745 681 byte
L'idea di base è quella di fare un grafico ponderato delle possibili mosse. I pesi sono il tempo necessario per spostarsi da un luogo all'altro. Il percorso con il minor peso sarà il più veloce.
Le cifre di input sono inserite in una matrice rettangolare r by c (righe per colonne) e quindi entrano in gioco tre rappresentazioni distinte: (1) un grafico a griglia r by c, in cui ciascun vertice corrisponde a una cella della matrice, (2) (r c) da (r c) matrice di adiacenza ponderata che contiene pesi corrispondenti al tempo impiegato (2, 3 o 11 minuti) per spostarsi da una posizione (nel grafico a griglia) a un'altra e (3) una direzione , grafico di adiacenza ponderato costruito dalla matrice.
Il grafico a griglia aiuta a determinare quali celle (cioè quali vertici) sono eventualmente raggiungibili da ciascun vertice - "probabilmente raggiungibile" perché una cella vicina non deve essere solo destra, sinistra, sopra o sotto una data cella. Il valore deve inoltre trovarsi entro 1 unità di distanza dal vicino (ad esempio, un 3 non si collega a un vicino 5 o un 1). Se il vertice a
non è collegato al verticeb
le celle della matrice di adiacenza {a, b} e {b, a} avranno un valore di ∞. Di conseguenza, il grafico di adiacenza ponderato non avrà un bordo da a a b, né da b a a.
Il grafico di adiacenza ponderato serve a determinare la distanza minima ( GraphDistance
) e il percorso più breve tra i vertici. Il percorso ottimale deve iniziare con 1, toccare ciascuno dei picchi e tornare a 1. In questo caso, "percorso più breve" non è necessariamente quello con il minor numero di mosse. È quello con il tempo complessivo più breve, misurato in pesi del bordo.
golfed
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]]
Forma più lunga e più leggibile
(*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]]]
test
weights["4 5
32445
33434
21153
12343"]
96.
weights@"2 7
6787778
5777679"
75.
weights@"3 4
1132
2221
1230"
51.
Spiegazione
Pensa alle righe 2-5 del seguente input
"4 5
32445
33434
21153
12343"
come rappresentante una matrice con 4 righe e 5 colonne:
dove ogni vertice corrisponde a una cifra dall'array di input: 3 è al vertice 1, 2 è al vertice 2, 4 è al vertice 3, un altro 4 al vertice 4, 5 al vertice 5, ecc. Il grafico della griglia è solo un grezzo approssimazione del grafico a cui miriamo. Non è indirizzato. Inoltre, alcuni dei bordi non saranno disponibili. (Ricorda: non possiamo spostarci da una posizione a un'altra che è più di 1 unità di altezza sopra o sotto quella corrente.) Ma il grafico della griglia ci permette di trovare facilmente quei vertici che si trovano accanto a qualsiasi vertice scelto. Ciò riduce il numero di spigoli che dobbiamo considerare, nel primo esempio (una griglia 4 per 5), da 400 (20 * 20) a 62 (31 * 2 è il numero di spigoli nel grafico della griglia). Nello stesso esempio, solo 48 dei bordi sono operativi; 14 non lo sono.
La seguente matrice di adiacenza ponderata 20 per 20 rappresenta la distanza tra tutte le coppie di vertici dal grafico della griglia.
Il codice chiave che decide su quale numero assegnare è riportato di seguito.
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}->∞}]
La cella {1,2} - in una indicizzazione - contiene il valore 2 perché lo spostamento dal vertice 1 al vertice 2 è in discesa. La cella {2,1} contiene 11 perché il passaggio dal vertice 2 al vertice 1 è in salita. I 3 nelle celle {1,6} e {6,1} indicano che il movimento non è né in alto né in basso. La cella {1,1} contiene ∞ perché non è connessa a se stessa.
Il grafico seguente mostra la struttura alla base dell'input sopra. Le frecce colorate mostrano il percorso ottimale dal vertice 1 ai picchi (a 5 e 14) e di nuovo a 1. Le frecce blu corrispondono a movimenti allo stesso livello (3 min); le frecce rosse indicano la salita (11 min.) e le frecce verdi indicano la discesa (2 min).
Il percorso dal vertice 1 (cella {1,1} ai due picchi e ritorno al vertice 1:
3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3
96