Mathematica 745 681 ไบต์
แนวคิดพื้นฐานคือการทำกราฟถ่วงน้ำหนักของการเคลื่อนไหวที่เป็นไปได้ น้ำหนักคือเวลาที่ใช้ในการย้ายจากที่หนึ่งไปอีกที่หนึ่ง เส้นทางที่มีน้ำหนักน้อยที่สุดจะเป็นเส้นทางที่รวดเร็วที่สุด
ตัวเลขที่ป้อนเข้าจะถูกวางในอาร์เรย์ r โดย c (แถวเรียงตามแถว) อาร์เรย์สี่เหลี่ยมจากนั้นมีการนำเสนอสามรูปแบบที่แตกต่างกันออกไป: (1) r โดย c กราฟกราฟที่แต่ละจุดยอดสอดคล้องกับเซลล์ในอาร์เรย์ (2) (r c) โดย (r c) เมทริกซ์ adjacency ถ่วงน้ำหนักที่เก็บน้ำหนักให้สอดคล้องกับเวลาที่ใช้ (2, 3, หรือ 11 นาที) เพื่อย้ายจากตำแหน่งหนึ่ง (ในกราฟกริด) ไปยังอีกตำแหน่งหนึ่งและ (3) ตำแหน่งกำกับ กราฟ adjacency ถ่วงน้ำหนักที่สร้างจากเมทริกซ์
กราฟกริดช่วยกำหนดว่าเซลล์ใด (เช่นจุดยอด) ที่สามารถเข้าถึงได้จากจุดสุดยอดแต่ละจุด - "อาจเข้าถึงได้" เพราะเซลล์ข้างเคียงต้องไม่เพียง แต่ถูกต้องซ้ายด้านบนหรือด้านล่างของเซลล์ที่กำหนด ค่าของมันต้องอยู่ในระยะ 1 หน่วยจากเพื่อนบ้าน (เช่น 3 ไม่เชื่อมต่อกับเพื่อนบ้าน 5 หรือ 1) หากจุดยอดa
ไม่ได้เชื่อมต่อกับจุดสุดยอดb
ดังนั้นเมทริกซ์เซลล์ adjacency {a, b} และ {b, a} จะมีค่าเป็น∞ ดังนั้นกราฟ adjacency ที่ถ่วงน้ำหนักจะไม่มีขอบจาก a ถึง b หรือจาก b ถึง a
กราฟ adjacency ที่ถ่วงน้ำหนักทำหน้าที่กำหนดระยะทางต่ำสุด ( 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 หน่วยเหนือหรือใต้ตำแหน่งปัจจุบัน) แต่กราฟกริดช่วยให้เราค้นหาจุดยอดเหล่านั้นที่อยู่ถัดจากจุดยอดที่เลือก สิ่งนี้ช่วยลดจำนวนของขอบที่เราต้องพิจารณาในตัวอย่างแรก (a 4 คูณ 5 grid) จาก 400 (20 * 20) ถึง 62 (31 * 2 คือจำนวนของขอบในกราฟกริด) ในตัวอย่างเดียวกันมีเพียง 48 ของขอบที่ทำงาน 14 ไม่ใช่
เมทริกซ์ adjacency แบบถ่วงน้ำหนัก 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