Toán học 745 681 byte
Ý tưởng cơ bản là tạo ra một biểu đồ trọng số của các bước di chuyển có thể. Trọng lượng là thời gian cần thiết để di chuyển từ nơi này sang nơi khác. Con đường có trọng lượng ít nhất sẽ là nhanh nhất.
Các chữ số đầu vào được đặt trong một r hình chữ nhật r (c theo hàng) và sau đó ba biểu diễn riêng biệt xuất hiện: (1) một biểu đồ lưới r, c, trong đó mỗi đỉnh tương ứng với một ô trong mảng, (2) (r c) bởi (r c) ma trận kề kề có trọng số giữ trọng số tương ứng với thời gian (2, 3 hoặc 11 phút) để di chuyển từ một vị trí (trong biểu đồ lưới) sang vị trí khác và (3) theo hướng , đồ thị kề kề có trọng số được xây dựng từ ma trận.
Biểu đồ lưới giúp xác định các ô nào (tức là đỉnh nào) có thể tiếp cận được từ mỗi đỉnh - "có thể tiếp cận được" bởi vì một ô lân cận không chỉ phải ở bên phải, bên trái, bên trên hoặc bên dưới một ô đã cho. Giá trị của nó cũng phải nằm trong khoảng 1 đơn vị khoảng cách từ hàng xóm (ví dụ: 3 không kết nối với 5 hoặc 1 lân cận). Nếu đỉnh a
không được kết nối với đỉnh b
thì các ô ma trận kề là {a, b} và {b, a} sẽ có giá trị là. Theo đó, biểu đồ kề kề có trọng số sẽ không có cạnh từ a đến b, cũng không từ b đến a.
Biểu đồ kề kề có trọng số phục vụ để xác định khoảng cách tối thiểu ( GraphDistance
) và tuyến đường ngắn nhất giữa bất kỳ đỉnh nào. Đường dẫn tối ưu phải bắt đầu bằng 1, chạm vào từng đỉnh và trở về 1. Trong trường hợp này, "tuyến đường ngắn nhất" không nhất thiết là đường có ít di chuyển nhất. Đây là một trong những có thời gian tổng thể ngắn nhất, được đo bằng trọng lượng cạnh.
Chơi gôn
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]]
Hình thức dài hơn, dễ đọc hơn
(*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]]]
Xét nghiệm
weights["4 5
32445
33434
21153
12343"]
96.
weights@"2 7
6787778
5777679"
75.
weights@"3 4
1132
2221
1230"
51.
Giải trình
Hãy nghĩ về các dòng 2-5 của đầu vào sau đây
"4 5
32445
33434
21153
12343"
như đại diện cho một mảng với 4 hàng và 5 cột:
Trong đó mỗi đỉnh tương ứng với một chữ số từ mảng đầu vào: 3 nằm ở đỉnh 1, 2 ở đỉnh 2, 4 ở đỉnh 3, 4 khác ở đỉnh 4, 5 ở đỉnh 5, v.v. Biểu đồ lưới chỉ là một phần thô xấp xỉ đồ thị mà chúng ta đang hướng tới. Nó là vô hướng. Hơn nữa, một số các cạnh sẽ không có sẵn. (Hãy nhớ rằng: chúng ta không thể di chuyển từ vị trí này sang vị trí khác lớn hơn 1 đơn vị chiều cao trên hoặc dưới vị trí hiện tại.) Nhưng biểu đồ lưới cho phép chúng ta dễ dàng tìm thấy các đỉnh nằm cạnh bất kỳ đỉnh được chọn nào. Điều này làm giảm số cạnh mà chúng ta cần xem xét, trong ví dụ đầu tiên (lưới 4 x 5), từ 400 (20 * 20) xuống 62 (31 * 2 là số cạnh trong biểu đồ lưới). Trong cùng một ví dụ, chỉ có 48 trong số các cạnh là hoạt động; 14 thì không.
Ma trận kề kề 20 x 20 sau đây biểu thị khoảng cách giữa tất cả các cặp đỉnh từ biểu đồ lưới.
Mã khóa quyết định số nào sẽ được gán bên dưới.
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} - trong một chỉ mục - chứa giá trị 2 vì việc di chuyển từ đỉnh 1 sang đỉnh 2 đang xuống dốc. Ô {2.1} chứa 11 vì việc di chuyển từ đỉnh 2 sang đỉnh 1 là khó khăn. Số 3 trong các ô {1,6} và {6,1} biểu thị rằng chuyển động không lên hoặc xuống. Ô {1,1} chứa ∞ vì nó không được kết nối với chính nó.
Biểu đồ sau cho thấy cấu trúc bên dưới đầu vào trên. Mũi tên màu hiển thị đường dẫn tối ưu từ đỉnh 1 đến các đỉnh (tại 5 và 14) và quay lại 1. Mũi tên màu xanh tương ứng với các bước di chuyển ở cùng cấp độ (3 phút); mũi tên màu đỏ có nghĩa là đi lên (11 phút) và mũi tên màu xanh lá cây biểu thị sự đi xuống (2 phút).
Đường dẫn từ đỉnh 1 (ô {1,1} đến hai đỉnh và quay lại đỉnh 1:
3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3
96