Luogu P1363 幻象迷宫
题目:幻象迷宫
题目链接:https://www.luogu.com.cn/problem/P1363
题意:有一可由无数个.
为路,#
为墙,S
为起始点。现由起点出发,试问通过上下左右移动是否可到达距离起点的无限远处。
分析:在起始迷宫(即所有点的坐标满足S
点出发可到达的点集记为S
点与起始迷宫的S
点连通,换而言之,即是说明从起始迷宫的S
点出发可以去到无限远处的迷宫的S
点。
思路:从起点出发开始搜索,若迷宫中某一相对位置在不同迷宫中走过2次,即说明可从起点走到无限远处。
实现:dfs(更优,有可能更快搜到符合能走到无限远处的条件) / bfs
时间复杂度:迷宫范围为
dfs解法参考代码:
【注意】该题本质是能否到达问题,不需回溯;求路径数问题才要回溯。
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define endl '\n'
int n,m,flag,ax,ay;
char g[1510][1510];
int st[1510][1510];
int to[1510][1510][2];//记录点(x,y)被搜索到的迷宫所在图中的位置
int dx[4]={-1,1,0,0},dy[4]={0,0,1,-1};
void dfs(int x,int y,int sx,int sy){
//(x,y)表示 点在迷宫中的一相对位置(即点的位置)
//(sx,sy)表示 当前点所在的迷宫处于图中的位置(即迷宫的位置)
if(flag) return;
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
int nsx=sx,nsy=sy;
if(nx>=n) nsy++;
else if(nx<0) nsy--;
else if(ny>=m) nsx++;
else if(ny<0) nsx--;
nx=(nx+n)%n,ny=(ny+m)%m;
if(g[nx][ny]=='#') continue;
if(st[nx][ny]){
if(nsx!=to[nx][ny][0]||nsy!=to[nx][ny][1]){
flag=1;//若在不同迷宫到达过相同位置->Yes
return;
}
else continue;
}
st[nx][ny]=1;
to[nx][ny][0]=nsx;
to[nx][ny][1]=nsy;
dfs(nx,ny,nsx,nsy);
}
}
void solve(){
while(cin>>n>>m){
flag=0;
memset(st,0,sizeof(st));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>g[i][j];
if(g[i][j]=='S') ax=i,ay=j;
}
}
st[ax][ay]=1;
to[ax][ay][0]=0;
to[ax][ay][1]=0;
dfs(ax,ay,0,0);
if(flag) cout<<"Yes\n";
else cout<<"No\n";
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T=1;
//cin>>T;
while(T--) solve();
return 0;
}
bfs解法参考代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define endl '\n'
int n,m,flag,ax,ay;
char g[1510][1510];
int st[1510][1510];
int to[1510][1510][2];//记录点(x,y)被搜索到的迷宫所在图中的位置
int dx[4]={-1,1,0,0},dy[4]={0,0,1,-1};
struct place{
int x,y,sx,sy;
//(x,y)表示 点在迷宫中的一相对位置(即点的位置)
//(sx,sy)表示 当前点所在的迷宫处于图中的位置(即迷宫的位置)
};
void solve(){
while(cin>>n>>m){
flag=0;
memset(st,0,sizeof(st));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>g[i][j];
if(g[i][j]=='S') ax=i,ay=j;
}
}
queue<place>q;
st[ax][ay]=1;
to[ax][ay][0]=0;
to[ax][ay][1]=0;
q.push({ax,ay,0,0});
//先标记,再入队,可减少入队数
while(!q.empty()){
place now=q.front();
q.pop();
for(int i=0;i<4;i++){
int nx=now.x+dx[i],ny=now.y+dy[i];
int nsx=now.sx,nsy=now.sy;
if(nx<0) nsy--;
else if(nx>=n) nsy++;
else if(ny<0) nsx--;
else if(ny>=m) nsx++;
nx=(nx+n)%n,ny=(ny+m)%m;
if(g[nx][ny]=='#') continue;
if(st[nx][ny]){
if(to[nx][ny][0]!=nsx||to[nx][ny][1]!=nsy){
//若在不同迷宫到达过相同位置->Yes
flag=1;
break;
}
}
else{
st[nx][ny]=1;
to[nx][ny][0]=nsx;
to[nx][ny][1]=nsy;
q.push({nx,ny,nsx,nsy});
}
}
}
if(flag) cout<<"Yes\n";
else cout<<"No\n";
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T=1;
//cin>>T;
while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架