简单广度搜索

题目描述

Knight Moves
Problem Description
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

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

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.

对于这道题,我需要普及一个只知识点国际象棋走法,可以走8个方向
在这里插入图片描述
那么现在切入正题,对于广度优先搜索,我们用到了队列。
我们从起始点开始走,分别走到八个方向上并在每个方向上判断是否已到达终点。如到达,直接输出步数,否则,入队列。
在每判断一点时,该点都要出队列,且每一判断的点,都是位于队首的点。
我们先来看一下实现深搜的代码

//这是伪码
int x1,y1,x2,y2;//起始点与终点坐标
int i;
int mmap[10][10];//定义棋盘
int dir[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};//定义下一步的八个方向
struct node   //结构体,存放当前点的位置坐标,和已经走得的步数
{
    int x;
    int y;
    int steps;
};
node start,finish;  //起点和终点
int bfs()
{
    memset(mmap,0,sizeof(mmap));    //先将整个棋盘刷成0
    node per,cur;   //per代表上一个位置。cur代表当前位置
    start.steps=0;  //起始步数为0
    queue<node>q;
    q.push(start);  //让start先进队
    mmap[start.x][start.y]=1; //始点标记为1
    while(!q.empty())   //只要队列非空进入循环体
    {
        per=q.front();  //per是当前的位置
        q.pop();        //队首元素出队
        if(per.x==finish.x&&per.y==finish.y)//判断是否到达终点
            return per.steps;
        for(i=0;i<8;i++)
        {
            cur.x=per.x+dir[i][0];
            cur.y=per.y+dir[i][1];
            if(cur.x<1||cur.x>8||cur.y<1||cur.y>8)
                continue;
            mmap[cur.x][cur.y]=1;
            cur.steps=per.steps+1;
            q.push(cur);
        }
    }
    return -1;
}

接下来是该题目的完整代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int x1,y1,x2,y2;//起始点与终点坐标
int i;
int mmap[10][10];//定义棋盘
int dir[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};//定义下一步的八个方向
struct node   //结构体,存放当前点的位置坐标,和已经走得的步数
{
    int x;
    int y;
    int steps;
};
node start,finish;  //起点和终点
int bfs()
{
    memset(mmap,0,sizeof(mmap));    //先将整个棋盘刷成0
    node per,cur;   //per代表上一个位置。cur代表当前位置
    start.steps=0;  //起始步数为0
    queue<node>q;
    q.push(start);  //让start先进队
    mmap[start.x][start.y]=1; //始点标记为1
    while(!q.empty())   //只要队列非空进入循环体
    {
        per=q.front();  //per是当前的位置
        q.pop();        //队首元素出队
        if(per.x==finish.x&&per.y==finish.y)//判断是否到达终点
            return per.steps;
        for(i=0;i<8;i++)
        {
            cur.x=per.x+dir[i][0];
            cur.y=per.y+dir[i][1];
            if(cur.x<1||cur.x>8||cur.y<1||cur.y>8)
                continue;
            mmap[cur.x][cur.y]=1;
            cur.steps=per.steps+1;
            q.push(cur);
        }
    }
    return -1;
}
int main()
{
    int mmin,t1,t2;
    char s1,s2;
    while(scanf("%c%d %c%d",&s1,&t1,&s2,&t2)!=EOF)
    {
        getchar();
        x1=s1-'a'+1;
        y1=t1;
        x2=s2-'a'+1;
        y2=t2;
        start.x=x1;
        start.y=y1;
        finish.x=x2;
        finish.y=y2;
        if(start.x==finish.x&&start.y==finish.y)
            mmin=0;
        else
            mmin=bfs();
            printf("To get from %c%d to %c%d takes %d knight moves.\n",s1,t1,s2,t2,mmin);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值