ในหมากรุก เรารู้ว่าอัศวินสามารถกระโดดได้ในลักษณะพิเศษ สามารถย้ายช่องสี่เหลี่ยมสองช่องในแนวนอนและแนวตั้งหนึ่งช่องหรือแนวตั้งสองช่องหรือแนวตั้งสองช่อง และแนวนอนหนึ่งช่องในแต่ละทิศทาง ดังนั้นการเคลื่อนไหวทั้งหมดจึงดูเหมือนตัวอักษรภาษาอังกฤษ "L"
ในปัญหานี้ มีกระดานหมากรุกว่างเปล่า และอัศวินที่เริ่มจากตำแหน่งใดก็ได้ในกระดาน หน้าที่ของเราคือตรวจสอบว่าอัศวินสามารถเยี่ยมชมช่องสี่เหลี่ยมทั้งหมดในกระดานได้หรือไม่ เมื่อมันสามารถเยี่ยมชมช่องสี่เหลี่ยมทั้งหมดได้แล้วจึงวางจำนวนการกระโดดที่จำเป็นเพื่อไปยังตำแหน่งนั้นจากจุดเริ่มต้น
ปัญหานี้อาจมีวิธีแก้ไขได้หลายทาง แต่เราจะพยายามหาทางแก้ไขที่เป็นไปได้อย่างใดอย่างหนึ่ง
อินพุตและเอาต์พุต
Input: The size of a chess board. Generally, it is 8. as (8 x 8 is the size of a normal chess board.) Output: The knight’s moves. Each cell holds a number, that indicates where to start and the knight will reach a cell at which move. 0 59 38 33 30 17 8 63 37 34 31 60 9 62 29 16 58 1 36 39 32 27 18 7 35 48 41 26 61 10 15 28 42 57 2 49 40 23 6 19 47 50 45 54 25 20 11 14 56 43 52 3 22 13 24 5 51 46 55 44 53 4 21 12
อัลกอริทึม
isValid(x, y, โซลูชัน)
อินพุต - วาง x และ y และเมทริกซ์ของโซลูชัน
ผลลัพธ์ - ตรวจสอบว่า (x,y) อยู่ในตำแหน่งและยังไม่ได้กำหนด
Begin if 0 ≤ x ≤ Board Size and 0 ≤ y ≤ Board Size, and (x, y) is empty, then return true End
knightTour(x, y, ย้าย, โซล, xMove, yMove)
อินพุต - (x, y) ตำแหน่ง จำนวนการเคลื่อนไหว เมทริกซ์ของโซลูชัน และรายการการเคลื่อนไหว x และ y ที่เป็นไปได้
ผลลัพธ์ - เมทริกซ์โซลูชันที่อัปเดตหากมีอยู่
Begin if move = Board Size * Board Size, then //when all squares are visited return true for k := 0 to number of possible xMovement or yMovement, do xNext := x + xMove[k] yNext := y + yMove[k] if isValid(xNext, yNext, sol) is true, then sol[xNext, yMext] := move if knightTour(xNext, yNext, move+1, sol, xMove, yMove), then return true else remove move from the sol[xNext, yNext] to backtrack done return false End
ตัวอย่าง
#include <iostream> #include <iomanip> #define N 8 using namespace std; int sol[N][N]; bool isValid(int x, int y, int sol[N][N]) { //check place is in range and not assigned yet return ( x >= 0 && x < N && y >= 0 && y < N && sol[x][y] == -1); } void displaySolution() { for (int x = 0; x < N; x++) { for (int y = 0; y < N; y++) cout << setw(3) << sol[x][y] << " "; cout << endl; } } int knightTour(int x, int y, int move, int sol[N][N], int xMove[N], int yMove[N]) { int xNext, yNext; if (move == N*N) //when the total board is covered return true; for (int k = 0; k < 8; k++) { xNext = x + xMove[k]; yNext = y + yMove[k]; if (isValid(xNext, yNext, sol)) { //check room is preoccupied or not sol[xNext][yNext] = move; if (knightTour(xNext, yNext, move+1, sol, xMove, yMove) == true) return true; else sol[xNext][yNext] = -1;// backtracking } } return false; } bool findKnightTourSol() { for (int x = 0; x < N; x++) //initially set all values to -1 of solution matrix for (int y = 0; y < N; y++) sol[x][y] = -1; //all possible moves for knight int xMove[8] = { 2, 1, -1, -2, -2, -1, 1, 2 }; int yMove[8] = { 1, 2, 2, 1, -1, -2, -2, -1 }; sol[0][0] = 0; //starting from room (0, 0) if (knightTour(0, 0, 1, sol, xMove, yMove) == false) { cout << "Solution does not exist"; return false; } else displaySolution(); return true; } int main() { findKnightTourSol(); }
ผลลัพธ์
0 59 38 33 30 17 8 63 37 34 31 60 9 62 29 16 58 1 36 39 32 27 18 7 35 48 41 26 61 10 15 28 42 57 2 49 40 23 6 19 47 50 45 54 25 20 11 14 56 43 52 3 22 13 24 5 51 46 55 44 53 4 21 12