POJ-1915 Knight Moves(双向广搜BFS)

版权声明:Copyright : 李三金,原创文章转载标明出处即可。 https://blog.csdn.net/santa9527/article/details/54424903

POJ-1915 Knight Moves

Knight Moves
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 25321 Accepted: 11971

Description
Background
Mr Somurolov, fabulous chess-gamer indeed, asserts that no one else but him can move knights from one position to another so fast. Can you beat him?
The Problem
Your task is to write a program to calculate the minimum number of moves needed for a knight to reach one point from another, so that you have the chance to be faster than Somurolov.
For people not familiar with chess, the possible knight moves are shown in Figure 1.

这里写图片描述

Input
The input begins with the number n of scenarios on a single line by itself.
Next follow n scenarios. Each scenario consists of three lines containing integer numbers. The first line specifies the length l of a side of the chess board (4 <= l <= 300). The entire board has size l * l. The second and third line contain pair of integers {0, …, l-1}*{0, …, l-1} specifying the starting and ending position of the knight on the board. The integers are separated by a single blank. You can assume that the positions are valid positions on the chess board of that scenario.

Output
For each scenario of the input you have to calculate the minimal amount of knight moves which are necessary to move from the starting point to the ending point. If starting point and ending point are equal,distance is zero. The distance must be written on a single line.

Sample Input

3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1

Sample Output

5
28
0

Source
TUD Programming Contest 2001, Darmstadt, Germany

题目意思很简单,一个棋子如上图走法,问从起点到终点最短步数是多少。

数据范围给出最多可以构造一个300*300的棋盘,看大神直接用广搜写,直接当成数学题写,我是渣渣,第一次写双向广搜,练练手。

代码如下:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
int len,sx,sy,ex,ey;
int vis[305][305],path[305][305];//访问标记;记录到该点的步数
int dir[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};//棋子的八个方向
struct node
{
    int x,y;
//    int step;//本来想用这个计步数,但是不可以,手动推一个简单的样例就知道了
};
bool judge(int x,int y)//判断点是否在图中
{
    if(x>=0&&x<len&&y>=0&&y<len)
        return 1;
    return 0;
}
int doublebfs(int sx,int sy,int ex,int ey)
{
    int i;
    memset(vis,0,sizeof(vis));
    memset(path,0,sizeof(path));
    queue<node>q;
    while(!q.empty()) q.pop();
    node st,ed;
    st.x=sx;st.y=sy;
    vis[sx][sy]=1;//从起点开始搜索的标记为1
    q.push(st);//起点入队列

    ed.x=ex;ed.y=ey;
    vis[ex][ey]=2;//从终点开始搜索的标记为2
    q.push(ed);//终点入队列

    while(!q.empty())
    {
        st=q.front();
        q.pop();//每次去除队首元素后都要弹出
        for(i=0; i<8; i++)
        {
            ed.x=st.x+dir[i][0];
            ed.y=st.y+dir[i][1];

            if(!judge(ed.x,ed.y))//不符合条件的点不用理会
                continue;

            if(!vis[ed.x][ed.y])//没访问过的点
            {
                vis[ed.x][ed.y]=vis[st.x][st.y];//标记为它上一个的点的标记值
                path[ed.x][ed.y]=path[st.x][st.y]+1;//步数+1
                q.push(ed);//入列
            }
            else if(vis[st.x][st.y]!=vis[ed.x][ed.y])//访问过该点,但是上一个点和该点的访问标记不一样1!=3 表明到达中点
                return path[st.x][st.y]+path[ed.x][ed.y]+1;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&len);
        scanf("%d %d %d %d",&sx,&sy,&ex,&ey);
        if(sx==ex&&sy==ey) printf("0\n");//起点终点一致
        else
        printf("%d\n",doublebfs(sx,sy,ex,ey));
    }
}

以上。

猜你喜欢

转载自blog.csdn.net/santa9527/article/details/54424903