poj 2243 bfs(172ms)或者双向bfs(94ms)

本文介绍如何利用广度优先搜索(BFS)算法解决骑士在棋盘上的最短路径问题,包括单向和双向BFS的具体实现,并提供完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击打开链接

普通bfs:

//八方向bfs
#include <iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=10;
typedef pair<int,int>PII;
PII start,en;
int dist[maxn][maxn];
int dx[]={-2,-1,-2,-1,1,2,2,1};
int dy[]={-1,-2,1,2,-2,-1,1,2};
int bfs()
{
    memset(dist,-1,sizeof(dist));
    dist[start.first][start.second]=0;
    queue<PII> pq;
    while(!pq.empty()) pq.pop();
    pq.push(start);
    while(!pq.empty())
    {
        PII k=pq.front();
        pq.pop();
        if(k.first==en.first&&k.second==en.second) return dist[k.first][k.second];
        for(int i=0;i<8;i++)
        {
            int nx=k.first+dx[i],ny=k.second+dy[i];
            if(nx>=1&&nx<9&&ny>=0&&ny<8&&dist[nx][ny]==-1) {
                dist[nx][ny]=dist[k.first][k.second]+1;
                pq.push(PII(nx,ny));
            }
        }
    }
}
int main()
{
    char a[5],b[5];
    while(scanf("%s%s",a,b)==2)
    {
        start.first=a[1]-'0';                   //行数
        start.second=a[0]-'a';                  //列数
        en.first=b[1]-'0';
        en.second=b[0]-'a';
        printf("To get from %s to %s takes %d knight moves.\n",a,b,bfs());
    }
    return 0;
}

双向bfs:

//双向bfs
//双向bfs是指使用两个队列,一个队列保存从起点开始的状态,另一个队列保存从终点开始向前搜索的状态
//其主要需要注意的是每个状态是由起点搜索到的还是由终点搜索到的,这样当两种状态相交时把步数相加即为结果
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int>PII;
const int maxn=10;
int dx[]={-2,-1,-2,-1,1,2,2,1};
int dy[]={-1,-2,1,2,-2,-1,1,2};
PII start,en;
int dist[maxn][maxn];
int color[maxn][maxn];
int bfs()
{
    queue<PII>p1;                   //从起点开始搜索
    while(!p1.empty()) p1.pop();
    queue<PII>p2;                       //从终点开始搜索
    while(!p2.empty()) p2.pop();
    memset(dist,-1,sizeof(dist));
    memset(color,-1,sizeof(color));
    p1.push(start);
    p2.push(en);
    dist[start.first][start.second]=dist[en.first][en.second]=0;
    color[start.first][start.second]=1;
    color[en.first][en.second]=2;
    while(!p1.empty()||!p2.empty())
    {
        if(!p1.empty()) {
            PII k=p1.front();
            p1.pop();
            for(int i=0;i<8;i++)
            {
                int nx=k.first+dx[i],ny=k.second+dy[i];
                if(nx>=1&&nx<9&&ny>=0&&ny<8) {
                    if(color[nx][ny]==-1) {
                        color[nx][ny]=1;
                        dist[nx][ny]=dist[k.first][k.second]+1;
                        p1.push(PII(nx,ny));
                    }
                    else if(color[nx][ny]==2) return dist[nx][ny]+dist[k.first][k.second]+1;
                }
            }
        }
        if(!p2.empty()) {
            PII k1=p2.front();
            p2.pop();
            for(int i=0;i<8;i++)
            {
                int nx=k1.first+dx[i],ny=k1.second+dy[i];
                if(nx>=1&&nx<9&&ny>=0&&ny<8) {
                    if(color[nx][ny]==-1) {
                        color[nx][ny]=2;
                        dist[nx][ny]=dist[k1.first][k1.second]+1;
                        p2.push(PII(nx,ny));
                    }
                    else if(color[nx][ny]==1) return dist[nx][ny]+dist[k1.first][k1.second]+1;
                }
            }
        }
    }
}
int main()
{
    char a[5],b[5];
    while(scanf("%s%s",a,b)==2)
    {
        start.first=a[1]-'0';                   //行数
        start.second=a[0]-'a';                  //列数
        en.first=b[1]-'0';
        en.second=b[0]-'a';
        if(start.first==en.first&&start.second==en.second) 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值