1372 Knight Moves (DFS做法)

博客围绕旅行骑士问题(TKP)展开,朋友认为确定棋盘上两格间骑士最小移动步数是难题,而实际相反。要求编写程序,输入两格,输出最短移动步数。还提到用BFS比DFS更快,因要找最小值。

A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part.

Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b.

Input Specification

The input file will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.

Output Specification

For each test case, print one line saying "To get from xx to yy takes n knight moves.".

Sample Input

e2 e4
a1 b2
b2 c3
a1 h8
a1 h7
h8 a1
b1 c3
f6 f6

Sample Output

To get from e2 to e4 takes 2 knight moves.
To get from a1 to b2 takes 4 knight moves.
To get from b2 to c3 takes 2 knight moves.
To get from a1 to h8 takes 6 knight moves.
To get from a1 to h7 takes 5 knight moves.
To get from h8 to a1 takes 6 knight moves.
To get from b1 to c3 takes 1 knight moves.
To get from f6 to f6 takes 0 knight moves.

 DFS的虽然也能AC但是不如BFS快,因为他是找最小值,BFS显然更快。

#include<cstdio>
#include<iostream>

using namespace std;

int maps[8][8] = {0};
static int dir[2][8] = {{-1, -1, +1, +1, -2, -2, +2, +2},
                        {-2, +2, -2, +2, -1, +1, -1, +1}};

int x2, y2;
int minClue;

bool isThere(int x, int y){
    if(x < 0 || x > 7){
        return false;
    }
    if(y < 0 || y > 7){
        return false;
    }
    return true;
}
int DFS(int x, int y, int l)
{
    if(x==x2&&y==y2 && minClue > l){
            //printf("x:%d y:%d\n", x2, y2);
        minClue = l;
        return 0;
    }
    if(maps[x][y] > l && isThere(x, y)){
        maps[x][y] = l;
        for(int i=0; i<8; i++){
            DFS(x+dir[0][i], y+dir[1][i], l+1);
        }
    }
}

void init()
{
    minClue = 10000;
    for(int i=0; i<8; i++){
        for(int j=0; j<8; j++){
            maps[i][j]=100;
        }
    }
    return;
}

int main()
{

    char s1[5];
    char s2[5];
    int x1,y1;
    while(cin>>s1>>s2){
        init();
        x1 = (int)(s1[0]-'a');
        y1 = (int)(s1[1]-'1');
        x2 = (int)(s2[0]-'a');
        y2 = (int)(s2[1]-'1');
        DFS(x1, y1, 0);
        printf("To get from %s to %s takes %d knight moves.\n",s1,s2, minClue);
    }
    return 0;
}

 

### 骑士周游问题的深度优先搜索算法解决方案 #### 构建骑士周游图 为了应用深度优先搜索来解决骑士周游问题,首先需要将棋盘上的每一个位置视为图的一个节点。两个节点之间存在边当且仅当这两个位置可以通过马步相互到达。对于标准的8×8国际象棋棋盘而言,这样的图可以预先构建好以便后续使用[^3]。 #### 深度优先搜索实现 一旦图形结构准备完毕,就可以利用深度优先搜索尝试寻找一条能够访问所有节点恰好一次并且回到起点的路径。以下是Python代码示例: ```python def knight_tour(n, path, moves, x, y): move_x = [2, 1, -1, -2, -2, -1, 1, 2] move_y = [1, 2, 2, 1, -1, -2, -2, -1] if n == len(path): return True for i in range(8): next_x = x + move_x[i] next_y = y + move_y[i] if (next_x >= 0 and next_x < 8 and next_y >= 0 and next_y < 8 and not (next_x, next_y) in path): # 尝试移动至下一个坐标 path.append((next_x, next_y)) if knight_tour(n + 1, path, moves, next_x, next_y): return True # 如果此路不通,则回退至上一步 path.pop() return False def solve_knight_tour(): start_pos = (0, 0) visited_positions = [start_pos] possible_moves = [] if knight_tour(1, visited_positions, possible_moves, *start_pos): print("成功完成骑士周游:", visited_positions) else: print("未能找到完整的骑士周游路线") ``` 这段程序定义了一个`knight_tour`函数来进行递归式的DFS探索,并通过`solve_knight_tour`启动整个过程。注意这里实现了基本形式的DFS而未加入任何剪枝策略;实际应用中可能还需要考虑性能优化措施如可行性剪枝等[^4]。 #### 性能优化与剪枝技术 针对上述基础版DFS,在面对大规模输入时可能会遇到效率瓶颈。因此引入了几种常见的剪枝技巧以提升求解速度: - **可行性剪枝**:提前判断下一步是否合理; - **搜索顺序剪枝**:调整搜索方向使得更有可能成功的分支优先被考察; - **最优性剪枝**:适用于最小化/最大化目标场景下的裁剪; - **排除等效冗余**:减少重复工作量; - **记忆化搜索**:缓存中间结果防止多次计算相同状态。 这些方法可以帮助显著改善算法表现,尤其是在处理大型实例时显得尤为重要。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值