Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม

ปัญหาการเดินทางของอัศวิน


ในหมากรุก เรารู้ว่าอัศวินสามารถกระโดดได้ในลักษณะพิเศษ สามารถย้ายช่องสี่เหลี่ยมสองช่องในแนวนอนและแนวตั้งหนึ่งช่องหรือแนวตั้งสองช่องหรือแนวตั้งสองช่อง และแนวนอนหนึ่งช่องในแต่ละทิศทาง ดังนั้นการเคลื่อนไหวทั้งหมดจึงดูเหมือนตัวอักษรภาษาอังกฤษ "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