Knight Moves(双向BFS)

题目大意
一个棋盘有八行八列,给出起点和终点求骑士的最小移动步骤。
解题思路
如果使用前面的bfs应该也是可以的,但是我们从双向bfs的思路出发。
由于起点和终点都很明确,因此我们可以从起点和终点分别bfs,当两个bfs在扩展时出现重复扩展的状态,表明从起点出发和从终点出发的两条路径连通,根据bfs的性质(在队首的一定是扩展次数少的)可以得到此时骑士移动的次数就是最少次数,搜索结束。
源代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>

using namespace std;
const int MAX_SIZE = 10 + 5;
struct node {
    int x, y;
} st, ed;
const int dx[] = {-2, -1, -2, -1, 1, 2, 2, 1};
const int dy[] = {-1, -2, 1, 2, -2, -1, 1, 2};
int dist[MAX_SIZE][MAX_SIZE];
int vis[MAX_SIZE][MAX_SIZE];

bool is_point_in(const node &next) {
    return next.x >= 1 && next.x < 9 && next.y >= 0 && next.y < 8;
}

int bfs() {
    queue<node> que;
    memset(dist, -1, sizeof(dist));
    memset(vis, -1, sizeof(vis));
    que.push(st);
    que.push(ed);
    dist[st.x][st.y] = dist[ed.x][ed.y] = 0;
    vis[st.x][st.y] = 1;
    vis[ed.x][ed.y] = 2;
    while (!que.empty()) {
        node k = que.front();
        que.pop();
        for (int i = 0; i < 8; i++) {
            node next = k;
            next.x += dx[i];
            next.y += dy[i];
            if (is_point_in(next)) {
                if (vis[next.x][next.y] == -1) {
                    vis[next.x][next.y] = vis[k.x][k.y];
                    dist[next.x][next.y] = dist[k.x][k.y] + 1;
                    que.push(next);
                } else if (vis[next.x][next.y] != vis[k.x][k.y]) {
                    return dist[next.x][next.y] + dist[k.x][k.y] + 1;
                }
            }
        }
    }
}

int main() {
    char a[5], b[5];
    while (scanf("%s%s", a, b) != EOF) {
        st.x = a[1] - '0';
        st.y = a[0] - 'a';
        ed.x = b[1] - '0';
        ed.y = b[0] - 'a';
        if (st.x == ed.x && st.y == ed.y) {
            printf("To get from %s to %s takes 0 knight moves.\n", a, b);
        } else {
            printf("To get from %s to %s takes %d knight moves.\n", a, b, bfs());
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

同学yes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值