Mathematica 745 681 bytes
Ide dasarnya adalah membuat grafik tertimbang dari kemungkinan pergerakan. Bobot adalah waktu yang diperlukan untuk berpindah dari satu tempat ke tempat lain. Jalan dengan bobot paling sedikit akan menjadi yang tercepat.
Digit input ditempatkan dalam larik persegi panjang r by c (rows by kolom) dan kemudian tiga representasi berbeda berperan: (1) grafik grid r by c, di mana setiap titik bersesuaian dengan sel dalam array, (2) (r c) dengan (r c) matriks adjacency tertimbang yang menahan bobot sesuai dengan waktu yang dibutuhkan (2, 3, atau 11 menit) untuk berpindah dari satu lokasi (dalam grafik kisi) ke lokasi lain, dan (3) diarahkan , grafik kedekatan tertimbang dibangun dari matriks.
Grafik kisi membantu menentukan sel mana (yaitu simpul mana) yang mungkin dapat dijangkau dari masing-masing simpul - "mungkin dapat dijangkau" karena sel tetangga tidak boleh hanya sel kanan, kiri, atas atau di bawah sel yang diberikan. Nilainya juga harus berada dalam 1 unit jarak dari tetangga (mis., 3 tidak terhubung ke tetangga 5 atau 1). Jika simpul a
tidak terhubung ke simpul b
maka sel-sel matriks adjacency {a, b} dan {b, a} akan memiliki nilai ∞. Dengan demikian, grafik adjacency tertimbang tidak akan memiliki ujung dari a ke b, atau dari b ke a.
Grafik adjacency tertimbang berfungsi untuk menentukan jarak minimum ( GraphDistance
) dan rute terpendek antara setiap simpul. Jalur optimal harus dimulai dengan 1, menyentuh masing-masing puncak, dan kembali ke 1. Dalam hal ini, "rute terpendek" tidak harus dengan rute dengan pergerakan paling sedikit. Ini adalah satu dengan waktu keseluruhan terpendek, diukur dalam bobot tepi.
Golf
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]]
Bentuk yang lebih panjang dan lebih mudah dibaca
(*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]]]
Tes
weights["4 5
32445
33434
21153
12343"]
96.
weights@"2 7
6787778
5777679"
75.
weights@"3 4
1132
2221
1230"
51.
Penjelasan
Pikirkan baris 2-5 dari input berikut
"4 5
32445
33434
21153
12343"
mewakili array dengan 4 baris dan 5 kolom:
di mana setiap titik bersesuaian dengan digit dari array input: 3 berada di titik 1, 2 di titik 2, 4 di titik 3, 4 di titik 4, 5 di titik 5, dll. Grafik grid hanya kasar perkiraan grafik yang kami tuju. Itu tidak diarahkan. Selain itu, beberapa tepi tidak akan tersedia. (Ingat: kita tidak dapat berpindah dari posisi ke posisi lain yang lebih dari 1 satuan ketinggian di atas atau di bawah posisi saat ini.) Tetapi grafik kisi mari kita dengan mudah menemukan simpul yang berada di sebelah setiap simpul yang dipilih. Ini mengurangi jumlah sisi yang perlu kita pertimbangkan, pada contoh pertama (kisi 4 dengan 5), dari 400 (20 * 20) menjadi 62 (31 * 2 adalah jumlah tepi dalam grafik kisi). Dalam contoh yang sama, hanya 48 sisi yang beroperasi; 14 tidak.
Matriks adjacency tertimbang 20 kali 20 berikut mewakili jarak antara semua pasangan simpul dari grafik kisi.
Kode kunci yang menentukan nomor yang akan ditugaskan di bawah.
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}->∞}]
Sel {1,2} - dalam satu-pengindeksan - berisi nilai 2 karena perpindahan dari titik 1 ke titik 2 menurun. Sel {2,1} berisi 11 karena perpindahan dari titik 2 ke titik 1 adalah menanjak. Angka 3 pada sel {1,6} dan {6,1} menandakan bahwa pergerakannya tidak naik atau turun. Sel {1,1} berisi ∞ karena tidak terhubung dengan dirinya sendiri.
Grafik berikut menunjukkan struktur yang mendasari input di atas. Panah berwarna menunjukkan jalur optimal dari puncak 1 ke puncak (pada 5 dan 14) dan kembali ke 1. Panah biru sesuai dengan gerakan pada tingkat yang sama (3 menit); panah merah berarti pendakian (11 menit) dan panah hijau menunjukkan keturunan (2 menit).
Path dari vertex 1 (sel {1,1} ke dua puncak dan kembali ke vertex 1:
3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3
96