Toán học, 326 325 byte
Cảm ơn masterX224 đã chỉ ra một khoản tiết kiệm byte!
f[g_,w_,x_]:=(c={{1,1},{-1,1}};s=c.c/2;e=#<->#2&@@@#&;j=Join;h=FindShortestPath;t=#~Tuples~2&;a@d_:=e@Select[t@g,#-#2&@@#==d&];y@k=j@@(a/@j[s,c]);y@n=j@@(a/@{{1,2},{2,1},{-2,1},{-1,2}});v=Flatten[e@t@#&/@ConnectedComponents@a@#&/@#]&;y@r=v@s;y@b=v@c;Pick[p={b,k,n,r},z=Length[h[y@#,w,x]/.h@__->0]&/@p,Min[z~Complement~{0}]]);
Xác định một hàm flấy ba đối số: glà danh sách các cặp số nguyên được sắp xếp đại diện cho bảng wvà xcác cặp được sắp xếp đại diện cho các ô vuông bắt đầu và kết thúc. Đầu ra là tập hợp con {b, k, n, r}(đại diện cho giám mục, vua, hiệp sĩ và tân binh), có đường di chuyển tối thiểu giữa hai hình vuông. Ví dụ, trường hợp thử nghiệm thứ ba được gọi bởi f[{{0, 0}, {1, 1}, {1, 2}, {0, 3}}, {0, 0}, {0, 3}]và trả về {k}; hai trường hợp thử nghiệm cuối cùng trở lại {k, n}và {}, tương ứng.
Chiến lược là dịch các hình vuông của bảng thành các đỉnh của đồ thị, trong đó các cạnh được xác định bởi các bước di chuyển của từng mảnh, sau đó sử dụng các thói quen biểu đồ tích hợp.
Phiên bản mã thân thiện hơn với người dùng:
1 f[g_, w_, x_] := ( c = {{1, 1}, {-1, 1}}; s = c.c/2;
2 e = # <-> #2 & @@@ # &; j = Join; h = FindShortestPath; t = #~Tuples~2 &;
3 a@d_ := e@Select[t@g, # - #2 & @@ # == d &];
4 y@k = j @@ (a /@ j[s, c]);
5 y@n = j @@ (a /@ {{1, 2}, {2, 1}, {-2, 1}, {-1, 2}});
6 v = Flatten[e@t@# & /@
7 ConnectedComponents@a@# & /@ #] &;
8 y@r = v@s; y@b = v@c;
9 Pick[p = {b, k, n, r},
10 z = Length[h[y@#, w, x] /. h@__ -> 0] & /@ p,
11 Min[z~Complement~{0}]]
12 );
Trong dòng 3, Select[g~Tuples~2, # - #2 & @@ # == dtìm tất cả các cặp đỉnh được sắp xếp có sự khác biệt là vectơ d; esau đó biến đổi từng cặp theo thứ tự như vậy thành một cạnh đồ thị vô hướng. Vậy alà một hàm tạo các cạnh giữa tất cả các đỉnh khác nhau bởi một vectơ cố định.
Đó là đủ để xác định, trong dòng 4 và 5, đồ thị của nhà vua y@k(mất công đoàn của các cạnh được tạo ra bởi các vectơ {1, 1}, {-1, 1}, {0, 1}, và {-1, 0}) và đồ thị của hiệp sĩ y@n(mà cũng làm như vậy với {1, 2}, {2, 1}, {-2, 1}, và {-1, 2}).
Trong dòng 7, ConnectedComponents@a@#lấy một trong các biểu đồ lân cận này và sau đó tìm các thành phần được kết nối của nó; điều này tương ứng với việc nhóm tất cả các phân đoạn của các đỉnh theo hướng đã cho (để một tân binh hoặc giám mục không phải di chuyển qua từng điểm một). Sau đó, e@t@#trên dòng 6 đặt các cạnh giữa mỗi cặp đỉnh trong cùng một thành phần được kết nối, sau đó được Flattened thành một biểu đồ duy nhất. Do đó, các dòng 6 đến 8 xác định biểu đồ của tân y@rbinh và biểu đồ của giám mục y@b.
Cuối cùng, các dòng 9 đến 11 chọn các phần tử {b, k, n, r}tạo ra đường đi ngắn nhất giữa hai đỉnh đích. FindShortestPathsẽ đưa ra một lỗi và trả về không đánh giá được nếu một đỉnh đích không xuất hiện trong biểu đồ (điều này sẽ xảy ra nếu không có cạnh nào phát ra từ nó), vì vậy chúng tôi sử dụng h@__ -> 0để trả về 0trong các trường hợp đó. Và việc thiếu một đường dẫn giữa các đỉnh hợp lệ sẽ trả về một danh sách độ dài 0, vì vậy hãy Min[z~Complement~{0}]tính độ dài của đường dẫn nhỏ nhất thực sự tồn tại, bỏ qua các trường hợp xấu ở trên.