广搜题(较复杂)




算法核心:

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;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值