刚才的 ABC D 题求调
  • 板块学术版
  • 楼主BartonMeow
  • 当前回复12
  • 已保存回复12
  • 发布时间2025/1/4 21:53
  • 上次更新2025/1/5 11:19:19
查看原帖
刚才的 ABC D 题求调
594203
BartonMeow楼主2025/1/4 21:53

先上代码。样例可以跑过,测试数据 AC38 WA19。

#include <iostream>
#include <queue>
#define MAXN 1001
using namespace std;
struct node {int x, y, dir;}; // 0: any; 1: ver; 2: hor
bool vis[MAXN][MAXN];
char g[MAXN][MAXN];
int dis[MAXN][MAXN];
int n, m, sx, sy, fx, fy;
int dxV[2] = {-1, 1}, dxH[2] = {0, 0}, dx[4] = {-1, 1, 0, 0};
int dyV[2] = {0, 0}, dyH[2] = {-1, 1}, dy[4] = {0, 0, -1, 1}; 
void bfs()
{
	queue<node> q;
	q.push((node){sx, sy, 0});
	vis[sx][sy] = true;
	dis[sx][sy] = 0;
	while (!q.empty())
	{
		node u = q.front();
		q.pop();
		for (int i = 0; i < (u.dir == 0 ? 4 : 2); i++)
		{
			int kx, ky;
			if (u.dir == 0)
				kx = u.x + dx[i], ky = u.y + dy[i];
			else if (u.dir == 1)
				kx = u.x + dxV[i], ky = u.y + dyV[i];
			else if (u.dir == 2)
				kx = u.x + dxH[i], ky = u.y + dyH[i];
			if (kx >= 1 && kx <= n && ky >= 1 && ky <= m && g[kx][ky] != '#' && !vis[kx][ky])
			{
				int kdir;
				if (u.dir == 0)
					kdir = i < 2 ? 2 : 1;
				else if (u.dir == 1)
					kdir = 2;
				else if (u.dir == 2)
					kdir = 1;
				q.push((node){kx, ky, kdir});
				dis[kx][ky] = dis[u.x][u.y] + 1;
				vis[kx][ky] = true;
				if (kx == fx && ky == fy)
				{
					cout << dis[kx][ky] << endl;
					return ;
				}
			}
		}
	}
	cout << -1 << endl;
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cin >> g[i][j];
			if (g[i][j] == 'S')
				sx = i, sy = j;
			else if (g[i][j] == 'G')
				fx = i, fy = j;
		}
	}
	bfs();
	return 0;
}

大概思路就是广搜。

其中 node 结构体中的 dir 可以为 0、1、2, 0 代表下一步可以走任意的方向(仅存在于第一步),1 代表下一步只能走垂直方向,2 代表下一步只能走水平方向。

对于几个偏移量数组,dxVdyV 表示垂直方向的偏移量,dxHdyH 表示水平方向的偏移量,dxdy 表示四个方向的偏移量。

内层循环根据下一步可走的方向来判断要遍历的数组。

剩下的就是一些常规的广搜操作。

那么请求解答:样例都是可以过的,而且主逻辑似乎没有问题,那么哪里写的有瑕疵?对于第一次就走四个方向,会不会对之后走的步骤有影响?别人有一种解法是第一遍只走水平或垂直(当成参数给出),然后跑两遍广搜,和我的方法有什么区别?

2025/1/4 21:53
加载中...