【题目】:https://www.luogu.com.cn/problem/P2199
暴力(详见代码)
//存图时先将墙和边界都赋值为false,这样Bfs时可以少判边界
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
struct node { //BFS队列
int x, y, t; //x坐标 + y坐标 + 到这个坐标的最短时间
node() {
}
node(const int &xx, const int &yy, const int &tt) { //初始化函数
x = xx, y = yy, t = tt;
}
};
bool map[5005][5005]; //输入的地图
bool vis[5005][5005]; //判断走过没
int n, m, walk[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {-1, -1}, {-1, 1}, {1, -1}};
//棋盘的长, 棋盘的宽, 可以走的四个方向 + 能看到的八个方向(注:walk数组的前四个方向是上下左右,后八个方向是右上,左上,右下,左下)
void seach(const int &x, const int &y, const int &ex, const int &ey); //BFS搜索并输出答案
bool pd(const int &x, const int &y, const int &ex, const int &ey); //判断是否看到奖杯
int main() {
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
char temp;
cin >> temp;
map[i][j] = ((temp == 'X') ? false : true); //如果是墙,就设为不能走,否则设为能走
}
}
int x, y, xx, yy;
while (scanf("%d%d%d%d", &x, &y, &xx, &yy)) { //一边读入一边循环
memset(vis, 0, sizeof(vis)); //清空上一次的痕迹
if (x == 0 && y == 0 && xx == 0 && yy == 0) {
break;
}
if (!map[x][y]) { //判断奖杯是否在墙上,如果在,直接输出就行
printf("Poor Harry\n");
continue;
}
seach(xx, yy, x, y); //BFS搜索
}
return 0;
}
void seach(const int &x, const int &y, const int &ex, const int &ey) {
queue<node> q;
q.push(node(x, y, 0));
vis[x][y] = true;
//定义队列并把当前坐标放进队列
while (!q.empty()) {
node now = q.front();
q.pop();
//弹出并赋值
if (pd(now.x, now.y, ex, ey)) { //如果可以看到奖杯,直接输出answer,然后return
printf("%d\n", now.t);
return;
}
for (int i = 0; i < 4; ++i) { //向四个方向移动(注:walk数组的前四个方向是上下左右,后八个方向是右上,左上,右下,左下)
int nx = now.x + walk[i][0];
int ny = now.y + walk[i][1];
if (map[nx][ny] && !vis[nx][ny]) { //如果没出界、没撞墙、没走过
vis[nx][ny] = true;
q.push(node(nx, ny, now.t + 1)); //那么就将这个位置的信息放进队列
}
}
}
printf("Poor Harry\n"); //走了那么久都没走到的话,就输出 Poor Harry
}
bool pd(const int &x, const int &y, const int &ex, const int &ey) {
for (int i = 0; i < 8; ++i) { //向八个方向看(注:walk数组的前四个方向是上下左右,后八个方向是右上,左上,右下,左下)
int nx = x, ny = y;
while (map[nx][ny]) { //不停的看,看到不能再看
if (nx == ex && ny == ey) { //如果能看到奖杯,就return true
return true;
}
nx += walk[i][0], ny += walk[i][1]; //如果没看到奖杯,就继续向下一个位置看
}
}
return false; //如果八个方向看完后都没看到的话,就return false
}