算法核心:
void bfs(int x, int y)
{
node p;
p.x = x;
p.y = y;
p.step= 0;
if (dd == 'E')
p.dir = 1;
if (dd == 'W')
p.dir = 2;
if (dd == 'S')
p.dir = 3;
if (dd == 'N')
p.dir = 4;
stt.push(p);
node qq;
while (!stt.empty())
{
qq = stt.front();
stt.pop();
if (qq.x == end_x && qq.y == end_y)
ans[++tot] = qq.step;
for (int i = 1; i <= 4; i++)//循环四个方向
{
int step = qq.step;
if (i != qq.dir)
{
step = qq.step + 1;
if ((i == 1 && qq.dir == 2) || (i == 2 && qq.dir == 1) || (i == 3 && qq.dir == 4) || (i == 4 && qq.dir == 3))
step = qq.step + 2;
}
for (int j = 1; j <= 3; j++)//循环走的步数
{
int xx = qq.x + brr[i][0]*j;
int yy = qq.y + brr[i][1]*j;
if (xx > n || xx<1 || yy>m || yy < 1|| map[xx][yy])
break;//因为比如往前走了两步就已经出界了,那么就没必要进行走三步了
if (vis[xx][yy] > step)
{
node p1;
p1.x = xx;
p1.y = yy;
p1.step = step + 1;
p1.dir = i;
stt.push(p1);
vis[xx][yy] = step;
}
}
}
}
}
解释一下,就是刚开始定义了:
这使得让方向和数组的i下标对应
先从刚开始的位置开始走,循环四个方向,这里用i的大小(1---4)表示方向,然后如果这个方向需要当前的方向转两次就step+2,转一次就加一,方向确定好了就来算朝这个方向走一步还是两步还是三步,
这个要注意一下,因为brr数组里面只会走一格所以需要乘以j,然后判断:
如果已经走好了的坐标的step比当前计算的step小,那么保存当前结点入队并且把这个结点的vis[xx][yy]=step
然后有几个需要注意的小坑:
1.需要把地图转换成点状地图:
因为你看原图中:
设定了一个点为障碍以后,那么整个正方形四个点就都是障碍了
2.边界问题:
这个问题几乎每个地图类的题目都要注意:‘
因为
这个机器是有半径的,题目中有给出,所以我们走的点不能走到边界上的一圈,所以要把边界上的一圈设置成1
源码送上:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int max_len = 51;
int map[max_len][max_len];//存地图
int vis[max_len][max_len];//存下每个位置需要的最少步数
int ans[5001] = { -1 };//把每次搜索可以走到的路线需要的步数记录下来
int start_x, start_y, end_x, end_y;
char dd;//刚开始输入的方向
int n, m;
int tot = 0;
int minl = 1000000;
typedef struct node {
int x;
int y;
int step;
int dir;//表示每个结点的方向
node *next;
};
int brr[5][2] = {
{0,0},
{0,1},
{0,-1},
{1,0},
{-1,0}
};
queue<node> stt;
void bfs(int x, int y)
{
node p;
p.x = x;
p.y = y;
p.step= 0;
if (dd == 'E')
p.dir = 1;
if (dd == 'W')
p.dir = 2;
if (dd == 'S')
p.dir = 3;
if (dd == 'N')
p.dir = 4;
stt.push(p);
node qq;
while (!stt.empty())
{
qq = stt.front();
stt.pop();
if (qq.x == end_x && qq.y == end_y)
ans[++tot] = qq.step;
for (int i = 1; i <= 4; i++)
{
int step = qq.step;
if (i != qq.dir)
{
step = qq.step + 1;
if ((i == 1 && qq.dir == 2) || (i == 2 && qq.dir == 1) || (i == 3 && qq.dir == 4) || (i == 4 && qq.dir == 3))
step = qq.step + 2;
}
for (int j = 1; j <= 3; j++)
{
int xx = qq.x + brr[i][0]*j;
int yy = qq.y + brr[i][1]*j;
if (xx > n || xx<1 || yy>m || yy < 1|| map[xx][yy])
break;//因为比如往前走了两步就已经出界了,那么就没必要进行走三步了
if (vis[xx][yy] > step)
{
node p1;
p1.x = xx;
p1.y = yy;
p1.step = step + 1;
p1.dir = i;
stt.push(p1);
vis[xx][yy] = step;
}
}
}
}
}
int get_ans()
{
int flag = minl;
for (int i = 1; i <= tot; i++)
{
if (ans[i] < flag)
flag = ans[i];
}
return flag;
}
int main()
{
cin >> n >> m;
bool asd;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)//转换成点图
{
cin >> asd;
if (asd)
{
map[i][j] = 1;
map[i - 1][j - 1] = 1;
map[i - 1][j] = 1;
map[i][j - 1] = 1;
}
}
map[n][i] = 1;
map[i][m] = 1;
}
cin >> start_x >> start_y >> end_x >> end_y;
cin >> dd;
memset(vis, 1, sizeof(vis));
bfs(start_x, start_y);
int ans = get_ans();
if (ans < minl)
{
cout << ans;
}
else
cout << "-1";
system("pause");
return 0;
}