首先吐槽一下,oj的报错让我摸不清头脑。
被一个点卡了快两个小时,这也是我写这份题解的原因,希望对你们有用。
题目描述
题目描述:
现在棋盘的大小不一定,由p,q给出,并且在棋盘中将出现障碍物(限制马的行动,与象棋走法相同)
输入描述:
第一行输入n表示有n组测试数据。
每组测试数据第一行输入2个整数p,q,表示棋盘的大小(1<=p,q<=100)。
每组测试数据第二行输入4个整数,表示马的起点位置与终点位置。(位置的取值范围同p,q)
第三行输入m表示图中有多少障碍。
接着跟着m行,表示障碍的坐标。
输出描述:
马从起点走到终点所需的最小步数。
如果马走不到终点,则输入“can not reach!”
输入样例:
2
9 10
1 1 2 3
0
9 10
1 1 2 3
8
1 2
2 2
3 3
3 4
1 4
3 2
2 4
1 3
输出样例:
1
can not reach!
题意
求马从起点(sx,sy)到终点(ex,ey) 最少需要多少步。
如果无法到达则输出"can not reach!"。
要考虑障碍物。
思路
通过 bfs 搜索,如果搜索到了则输出最少需要的步数,如果遍历完了整个图还是没有搜索到,则输出"can not reach!"。更多的细节看代码注释。
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 9;
//开全局变量方便后面dfs调用
int p, q, m;
int sx, sy, ex, ey;//起点(sx,sy),终点(ex,ey)
int a[105][105], b[105][105]; //数组a用来存图,b用来寸最少步数
bitset<105> vis[105]; //用来标记这个点是否
//枚举 8 种跳马的情况
int dx[8] = { 2,1,-1,-2,-2,-1,1,2 };
int dy[8] = { 1,2,2,1,-1,-2,-2,-1 };
//枚举 8 种跳马因障碍物无法移动的情况
int bbx[8] = { 1,0,0,-1,-1,0,0,1 };
int bby[8] = { 0,1,1,0,0,-1,-1,0 };
//判断点(x,y) 是否在棋盘上
int inmap(int x, int y)
{
if (x >= 1 && x <= p && y >= 1 && y <= q) return 1;
return 0;
}
//bfs 搜索
void bfs()
{
queue<pair<int, int>> qe;
qe.push({ sx,sy });//将起点入队
while (qe.size())
{
//取出队首元素
int x = qe.front().first, y = qe.front().second;
qe.pop();
vis[x][y] = true;
//如果该点为终点则直接返回
//也可以不写,因为后面入队的时候就会判一次是不是终点
if (x == ex && y == ey) return;
//枚举从点(x,y) 能跳到的8个位置
for (int i = 0; i < 8; i++)
{
int nx, ny;//用来记录将要跳到的点
nx = x + dx[i];
ny = y + dy[i];
int bx, by;//用来阻碍这次移动的障碍物的点
bx = x + bbx[i];
by = y + bby[i];
//首先判断是否在棋盘里面
//两个 if 也可以合成一个
if (inmap(nx, ny))
{
//如果符合入队的要求则将其入队
if (!vis[nx][ny] && !a[bx][by] && !a[nx][ny])
{
qe.push({ nx,ny });
vis[nx][ny] = true;
//算最少需要步数,这里可以不用min直接 b[nx][ny] = b[x][y] + 1
b[nx][ny] = min(b[nx][ny], b[x][y] + 1);
//前面说到的入队这里我们还会判一下,两个位置写哪里都可以
if (nx == ex && ny == ey)
{
vis[nx][ny] = 1;
return;
}
}
}
}
}
}
void solve()
{
//多组数据输入,每次输入数据前要将数据重置,防止之前的数据对本次测试产生干扰
memset(a, 0, sizeof a);
memset(b, 0x3f, sizeof b);// b记录最少需要的步数,所以将他赋值为无穷大
memset(vis, 0, sizeof vis);
//输入数据
cin >> p >> q;
cin >> sx >> sy >> ex >> ey;
cin >> m;
b[sx][sy] = 0;// 初始位置的最少步数为 0
for (int i = 1; i <= m; i++)
{
int x, y;
cin >> x >> y;
a[x][y] = 1;
//vis[x][y] = true;
//这个“vis[x][y] = true;”就是我卡快两个小时的元凶,其实还是自己考虑不周,
//本意是想直接在输入阶段就把障碍排除,不进行遍历,然后没考虑到终点位置是障碍的情况
//狂扇自己三大嘴巴子
}
//bfs 搜索
bfs();
if (vis[ex][ey]) cout << b[ex][ey] << '\n';
else cout << "can not reach!\n";
/*if (!vis[ex][ey]||b[ex][ey]>=N) cout << "can not reach!\n";
else cout << b[ex][ey] << '\n';*/
return;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int _ = 1;
cin >> _;
while (_--) solve();
return 0;
}
ok,到这里就结束了,希望你有所收获,上面的有问题也可以评论或者私信,看到了都会回的。