2016暑期集训---搜索(BFS 八方向马步问题)

做这题的时候是给自己定时做的,我觉得定时做一道题的效果很不错。这样我才能够专心地想这道题怎么写。这对于容易分心的我来说并不是一件很容易的事情。其实写完这道题还是很开心的,也是1A的,开心的原因是因为以前其实一直没有真正地懂搜索,只知道思想,但是敲不出代码。估计要是以前做的话,我是做不到今天这样的,“看题,想思路,敲代码,AC!”但是这次做到了,值得欣慰的是,我今年的暑期集训我一直秉承着决不看题解的态度来做题。虽然去年我也是基本上没看题解的,(结果去年集训的结果一团糟,糟心啊)只有不看题解,一道题完完全全地靠自己从看题到AC,这样子在看到OJ返回的AC才能体会到一种由衷的,无法言说的快感!
经过这两天的练习,我觉得我对bfs有了一个更深入的理解。至少我可以完完全全地把bfs的基础题一步一步敲出来了。继续加油!
题目是经典的BFS了
【题面】
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

【题面大意】给定一个n×n的棋盘,以及起点、终点。一个能走8个方向的马。求最少需要几步可以从起点到终点。经典的bfs
【解法】从起点开始,每次扩展8个方向。
【技巧】
将用来存放节点的结构体

struct Point{
    int x, y;
};

加上层数的信息,成为:

struct Point{
    int x, y;
    int depth;
};

就可以在搜索的时候携带层数信息进行搜索了。
【AC代码】

#include <cstdio>
#include <cstring>
#include <cstring>
#include <queue>
#define N 310
using namespace std;

struct Point{
    int x, y;
    int depth;
};
Point start;                                                ///起点
Point end;                                                  ///终点
int map[N][N];                                              ///地图
int n;                                                      ///棋盘大小
int ans;
int dx[8] = {-1, -2, -2, -1, 1, 2, 2, 1};
int dy[8] = {-2, -1, 1, 2, 2, 1, -1, -2};

bool check(Point p){
    if(map[p.x][p.y] == 0 && p.x >= 0 && p.x < n && p.y >= 0 && p.y < n){
        return true;
    }
    return false;
}



queue<Point>Q;
void bfs(Point p){
    Q.push(p);
    while(!Q.empty()){
        Point temp = Q.front();
        Q.pop();
        for(int i = 0; i < 8; i++){
            Point newPoint;
            newPoint.x = temp.x + dx[i];
            newPoint.y = temp.y + dy[i];
            if(check(newPoint)){
                if(newPoint.x == end.x && newPoint.y == end.y){
                    ans = temp.depth + 1;
                    return ;
                }
                map[newPoint.x][newPoint.y] = 1;
                newPoint.depth = temp.depth + 1;
                Q.push(newPoint);
            }
        }
    }
    return ;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        memset(map, 0, sizeof(map));
        ans = -1;
        scanf("%d", &n);
        scanf("%d%d", &start.x, &start.y);
        scanf("%d%d", &end.x, &end.y);
        if(start.x == end.x && start.y == end.y){
            printf("0\n");
        }
        else{
            map[start.x][start.y] = 1;
            start.depth = 0;
            bfs(start);
            printf("%d\n", ans);
        }
        while(!Q.empty()){
            Q.pop();
        }
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值