knight's

A Knight’s Watch

Recently I came across this interesting problem through Toptal (on Codility) which kept me thinking hard for a few days. Finally, I now have a solution to this problem and would like to share it here.

Problem:

Basically, the problem deals with a knight piece on an infinite chess board. Assuming the knight is positioned at (0,0) you are asked to calculate and print the shortest path that the knight can take to get to the target location.

knight1

My Approach:

So what is given here?

  1. The Knight’s movement is well defined i.e. it can only move in a ‘L’ shape.
  2. The Knight has option to move to any of the 8 different locations from it’s current position.

 

knight4

Now with these key points in mind, we can calculate which move will take the Knight closest to the given target i.e. move the knight in the direction of shortest distance.

For example: Suppose our target is located at (6,7).

cap1.PNG

Now, from (0,0) the Knight can move to following points: (1,2), (2,1), (-1,2), (-2,1), (-1,-2), (-2,-1), (1,-2) and (2,-1).

But out of these 8 points, the closest one is (1,2). So we move the knight to this position in first move. For each step we can use the same logic to move the Knight.

Hence, the Knight moves to (1,2) in first step, (3,3) in second, (4,5) in third and (6,6) in fourth move.

However, once the Knight reaches a proximity distance of 1 unit, we will have to keep in mind a separate logic to hit the target.

This is because if we stick to our logic of moving the knight towards the shortest distance in all places, what will happen is once the knight reaches a close proximity, the Knight will start going round and round the target but never actually hit the target.

From (6,6), the Knight could jump to (7,8). From (7,8) it could jump to (5,7) and to (7,5) and all but never actually jump to (6,7).

So, we have to create a separate rule for this scenario for our Knight.

Close Proximity Rule:

There are again 8 different close proximity points from the target location’s view point : (7,7), (7,8), (6,8), (5,8), (5,7), (5,6), (6,6) and (7,6).

These eight points can be categorized into 2 types. Either they lie on the axes or they lie on the diagonals from the given target.

Points on Axes: (7,7), (6,8), (5,7) and (6,6)

cart1

Points on Diagonals: (7,8), (5,8), (5,6) and (7,6)

cart2

Based on these two types, the Knight can hit the target in either 2 or 3 moves.

If the Knight was at a point on the diagonal say (5,6), from there it can jump (7,5) and then to (6,7) in 2 two moves. All diagonal points can access the target in the center in two steps.

Similarly, all points on the x-y axes can hit the target in 3 steps. For example, if the Knight was at (6,6), it can jump to points (8,7), then to (7,9) and finally t (6,7).

Now with this much knowledge we can create a program that can calculate the shortest path that our Knight has to take to hit any target on an infinite chess board!

My Implementation:

I have created a console application in C# to calculate the shortest path for the Knight to reach any stated target point with the above mentioned logic.

The application/project is available in git hub @ https://github.com/psovit/knightswatch

Please feel free to like, share and comment.

Thanks!

vitChess.jpg

骑士周游问题(Knight’s Tour)是图论与算法领域中的一个经典问题,其核心在于找出一条路径,使国际象棋中的“骑士”(马)从某一初始位置出发,恰好访问棋盘上的每一个格子一次。该问题本质上是一个回溯问题,具有NP难的复杂度,因此在算法设计中常作为递归与状态搜索的典型示例[^2]。 解决该问题的常见方法是回溯法,这是一种递归的方法,它尝试在每个可能的位置进行骑士的移动,如果当前位置是合法的并且未被访问过,则标记当前位置为已访问,并递归地探索下一个位置。如果在某个位置无法找到下一个合法的移动位置,则回溯到上一个位置,重新选择其他的移动方向。例如,C#实现Knight’s Tour算法的代码如下: ```csharp bool KnightTour(int x, int y, int moveCount) { // 标记当前位置为已访问 chessboard[x, y] = moveCount; // 所有格子都已经访问过,算法结束 if (moveCount >= BoardSize * BoardSize) { return true; } // 尝试在所有可能的移动方向上进行移动 for (int i = 0; i < 8; i++) { int nextX = x + moveX[i]; int nextY = y + moveY[i]; if (CanMove(nextX, nextY)) { if (KnightTour(nextX, nextY, moveCount + 1)) { return true; } } } // 回溯到上一个位置 chessboard[x, y] = -1; return false; } ``` 此外,也可以通过面向对象的方式来实现该算法,如定义一个KnightTour类,其中`isSafeMoveWithX:y:`方法用于检查骑士是否可以移动到指定位置,`printSolution`方法用于打印解决方案,`solveKnightTourUtilWithX:y:moveCount:`是递归函数用于查找骑士之旅的解决方案,`solveKnightTour`方法是入口函数用于启动解决骑士之旅问题的过程[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值