簡單廣度搜索

題目描述

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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章