Mathematica 745 681 байт
Основна ідея - скласти зважений графік можливих рухів. Ваги - це час, необхідний для переміщення з одного місця на інше. Шлях з найменшою вагою буде найшвидшим.
Вхідні цифри розміщуються у прямокутному масиві r на c (рядки за стовпцями), після чого вступають у дію три різні зображення: (1) сітка графіка r за c, де кожна вершина відповідає комірці в масиві, (2) (r c) за (r c) зваженою матрицею суміжності, яка утримує ваги, що відповідають часу, необхідному (2, 3 або 11 хвилин) для переміщення з одного місця (у графічній сітці) в інше, та (3) спрямованого , зважений графік суміжності, побудований з матриці.
Графік сітки допомагає визначити, які комірки (тобто які вершини) можливо досяжні з кожної вершини - "можливо досяжні", оскільки сусідня комірка повинна бути не лише правою, лівою, над або нижче даної комірки. Це значення також має бути в межах 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 на 5) з 400 (20 * 20) до 62 (31 * 2 - кількість ребер у графіку сітки). У цьому ж прикладі функціонують лише 48 ребер; 14 - ні.
Наступна зважена матриця примикання 20 на 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,2} - в одноіндексації - міститься значення 2, оскільки рух від вершини 1 до вершини 2 знаходиться вниз. В комірці {2,1} міститься 11, тому що перехід від вершини 2 до вершини 1 - в гору. 3 у клітинках {1,6} та {6,1} означають, що рух ні вгору, ні вниз. Клітина {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