Mathematica 745 681 bayt
Temel fikir, olası hareketlerin ağırlıklı bir grafiğini yapmaktır. Ağırlıklar bir yerden diğerine geçmenin zamanıdır. En az ağırlığa sahip olan yol en hızlı olacaktır.
Girdi haneleri r r'ye c (sütunlar halinde satırlar) dikdörtgen dizisine yerleştirilir ve sonra üç farklı gösterimler devreye girer: (1) her köşenin dizideki bir hücreye karşılık geldiği, r r'ye göre c ızgara grafiği, (2) (rc ) ( rc) bir konumdan (ızgara grafiğindeki) bir konumdan diğerine hareket etmek için geçen süreye (2, 3 veya 11 dakika) karşılık gelen ağırlıkları tutan ağırlıklı bitişik matris ile ve (3) yönlendirilmiş matristen oluşturulan ağırlıklı bitişik grafik.
Izgara grafiği, hangi hücrelerin (yani hangi köşelerin) her köşe noktasından muhtemelen ulaşılabilir olduğunu - "muhtemelen ulaşılabilir" olduğunu belirlemeye yardımcı olur, çünkü komşu bir hücre verilen bir hücrenin sadece sağ, sol, üstünde veya altında olmamalıdır. Değeri de komşuya 1 birim mesafede olmalıdır (örneğin, bir 3 komşu 5 veya 1'e bağlanmaz). Köşe tepe noktasına a
bağlı değilse b
, bitişik matris hücreleri {a, b} ve {b, a}, ∞ değerine sahip olacaktır. Buna göre, ağırlıklı bitiş grafiği, a'dan b'ye ya da b'den a'ya bir kenara sahip değildir.
Ağırlıklı bitişik grafik, GraphDistance
herhangi bir tepe noktası arasındaki minimum mesafeyi ( ) ve en kısa rotayı belirlemeye yarar . En uygun yol 1 ile başlamalı, her bir tepe noktasına dokunmalı ve 1'e geri dönmelidir. Bu durumda, "en kısa yol" mutlaka en az hareket yapan yol değildir. Kenar ağırlıkları ile ölçülen en kısa toplam süreye sahip olanıdır.
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]]
Daha uzun, daha okunabilir 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]]]
Testler
weights["4 5
32445
33434
21153
12343"]
96.
weights@"2 7
6787778
5777679"
75.
weights@"3 4
1132
2221
1230"
51.
açıklama
Aşağıdaki girişin 2-5 satırlarını düşünün
"4 5
32445
33434
21153
12343"
4 satırlı ve 5 sütunlu bir diziyi temsil eden:
her köşe giriş dizisinden bir basamağa karşılık gelir: 3 köşe 1'de, 2 köşe 2'de, 4 köşe 3'te, köşe 4, 5'de köşe 5, vb. 4'tür. Izgara grafiği sadece kaba hedeflediğimiz grafiğin yaklaştırılması. Bu yönlendirilmemiş. Ayrıca, bazı kenarlar kullanılamayacak. (Unutmayın: Bir konumdan diğerine 1 veya daha yüksek birimin üstünde olan bir konumdan diğerine geçemeyiz.) Ancak ızgara grafiği, seçilen herhangi bir tepe noktasının yanındaki köşeleri kolayca bulalım. Bu, ilk örnekte (4'e 5'lik bir ızgara), göz önünde bulundurmamız gereken kenar sayısını 400 (20 x 20) 'den 62'ye (31 * 2, ızgara grafiğindeki kenar sayısıdır) azaltır. Aynı örnekte, kenarların sadece 48'i çalışır durumda; 14 değil.
Aşağıdaki 20 x 20 ağırlıklı bitişik matris, ızgara grafiğindeki tüm köşe çiftleri arasındaki mesafeyi temsil eder.
Hangi numaraya atanacağına karar veren anahtar kodu aşağıdadır.
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}->∞}]
Hücre {1,2} - bir indekslemede - 2 değerini içerir çünkü köşe 1'den köşe 2'ye geçiş yokuş aşağıdır. Hücre {2,1} 11 içerir çünkü köşe 2'den köşe 1'e geçiş yokuş yukarıdır. {1,6} ve {6,1} hücrelerinde bulunan 3'ler hareketin ne aşağı ne de aşağı olduğunu gösterir. {1,1} hücresi, ∞ içerir çünkü kendisine bağlı değildir.
Aşağıdaki grafik yukarıdaki girişin altında yatan yapıyı göstermektedir. Renkli oklar, tepe 1'den tepe noktalarına (5 ve 14'te) ve 1'e geri dönüş için en uygun yolu gösterir. Mavi oklar, aynı seviyedeki (3 dakika) hareketlere karşılık gelir; kırmızı oklar yükselme (11 dak.) ve yeşil oklar iniş (2 dak) gösterir.
Köşe 1'den ({1,1} hücresinden iki tepe noktasına ve köşe 1'e geri giden yol:
3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3
96