T了几个点,WA了几个点,想到说传送门是可能再次使用的,不能用vis数组来判断,但细想下来,主要是传过去之后不能立马传回来,但是可能走一段之后再回到这个传送门,所以传送到的传送门是不能标记的。基于这个思想,我选择特判进入dfs时是否是传送门,是的话说明刚传到不能标记,否则就标记
改完后没有正确性问题了,,T了一半。
想想怎么记忆化搜索或者剪枝优化吧。
然而几乎是毫无思路了,因为传送门的存在,我想不到很优秀的记忆化状态,剪枝大概率也是玄学。
点开这道题标签,猛然看见BFS和最短路。
这才意识到这题用BFS更好,毕竟BFS的特性让他在求最短路径的时候有远超DFS的优势。
于是又开始打BFS。
因为觉得大同小异,所以几乎是直接把DFS代码复制了过去,但是却又T又M。
code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
struct coord {
int x, y;
};
struct status {
int x, y, step;
};
int walk[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int n, m, sx, sy, ans = 0x7fffffff;
char map[301][301];
coord tpGate[100][2];
queue<status> Q;
int cnt[100];
int ansArr[301][301];
bool vis[301][301];
bool is_tp(char ch)
{
return ch >= 'A' && ch <= 'Z';
}
void findTpEnd(int ch, int x, int y,int& dx, int& dy)
{
if (tpGate[ch][0].x == x && tpGate[ch][0].y == y)
{
dx = tpGate[ch][1].x, dy = tpGate[ch][1].y;
return ;
}
else
{
dx = tpGate[ch][0].x, dy = tpGate[ch][0].y;
return ;
}
}
void BFS()
{
Q.push({sx, sy, 0});
while(!Q.empty())
{
status node = Q.front();
Q.pop();
int x = node.x, y = node.y, step = node.step;
if (!is_tp(map[x][y]))
{
vis[x][y] = true;
}
if (map[x][y] == '=')
{
ans = step;
return ;
}
for (int i = 0; i < 4; i++)
{
int dx = x + walk[i][0], dy = y + walk[i][1];
if (dx < 1 || dx > n || dy < 1 || dy > m || vis[dx][dy] || map[dx][dy] == '#') continue;
if (is_tp(map[dx][dy]))
{
int tx, ty;
int temp = (int)map[dx][dy];
findTpEnd(temp, dx, dy, tx, ty);
if (cnt[temp] == 2)
{
vis[dx][dy] = true;
Q.push({tx, ty, step + 1});
vis[dx][dy] = false;
} else {
Q.push({dx, dy, step + 1});
vis[dx][dy] = false;
}
} else {
Q.push({dx, dy, step + 1});
vis[dx][dy] = false;
}
}
}
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> map[i][j];
if (is_tp(map[i][j]))
{
int temp = map[i][j];
tpGate[temp][cnt[temp]].x = i;
tpGate[temp][cnt[temp]].y = j;
cnt[temp]++;
}
if (map[i][j] == '@')
{
sx = i, sy = j;
}
}
}
BFS();
printf("%d", ans);
return 0;
}
- 回溯语句没删,合着BFS也回溯是吧
- 递归的思想直接照搬,剪枝那些也得删。
处理完之后TLE,没办法,不能偷懒,重写BFS。
这次学聪明了,不在for枚举坐标的时候特判传送门,而是枚举前直接特判传送门,如果是的话直接把当前操作的队列点改为传送后的队列点,一下省了一堆特判。
搞了三个半小时,终于AC。
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下