迷宫问题(图论)

🧱 迷宫 BFS 四大组装模块

  • 模块一:读图与侦察(找起点)

    • 动作 :两个 for 循环读入地图。

    • 核心细节 :看到 'S' 立刻把坐标记下来,顺手把 dist 数组全部刷成 -1(清空案发现场)。

  • 模块二:点火起步(发准考证)

    • 动作 :建队列 queue<pair<int, int>>,把起点塞进去。

    • 致命细节 :千万别忘了 dist[sx][sy] = 0。起跑前必须给起点挂上 0 步的牌子!

  • 模块三:十字雷达扫描(核心引擎)

    • 动作while 循环里套一个 4 次的 for 循环(利用 dx, dy 数组)。

    • 核心细节 :极其严密的"四重防弹衣"------nx, ny 不能越界、不能撞墙 (#)、不能去过 (dist != -1)。一旦发现 'E',立刻记录步数并强行刹车(break)。

  • 模块四:清算离场

    • 动作 :输出答案。没找到就老老实实输出 -1

迷宫

查看题解查看答案

题目描述

Time Limit: 1000 ms

Memory Limit: 256 mb

小 A 同学现在被困在了一个迷宫里面,他很想从迷宫中走出来,他可以 向上、向下、向左、向右移动、每移动一格都需要花费 1 秒的时间,不能够走到 边界之外。假设小 A 现在的位置在 S,迷宫的出口在 E,迷宫可能有多个出口。 问小 A 想要走到迷宫出口最少需要花费多少秒?

输入输出格式
输入描述:

有多组测试数据。 第一行输入两个正整数 H(0 < H <= 100)和 W(0 < W <= 100),分别表示迷 宫的高和宽。 接下来 H 行,每行 W 个字符(其中'*'表示路,'#'表示墙,'S'表示小 A 的位置,'E'表示迷宫出口)。 当 H 与 W 都等于 0 时程序结束。

输出描述:

输出小 A 走到迷宫出口最少需要花费多少秒,如果永远无法走到出口则输出"-1"。

输入输出样例
输入样例#:

复制

复制代码
3 3
S*#
**#
#*E
0 0
输出样例#:

复制

复制代码
4
题目来源
复制代码
天津大学/南开大学机试题
复制代码
#include<bits/stdc++.h>
using namespace std;

char g[105][105];
int dist[105][105];

int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

int main() {
	int h, w;
	while(cin>>h>>w){
		if(h == 0 && w == 0){
			break;
		}
		
		int sx = -1, sy = -1;
		for(int i = 0; i < h; i ++){//分清行列, 高是有几行, 宽是有几列 
			for(int j = 0; j < w; j ++){
				dist[i][j] = -1;//刚开始都标记为没走过 
				cin>>g[i][j];//输入迷宫 
				if(g[i][j] == 'S'){//初始位置 
					sx = i;
					sy = j;
				}
			}
		}
		
		queue<pair<int, int>> q;
		q.push({sx, sy});
		bool found = false;//是否找到了? 
		dist[sx][sy] = 0;
		
		while(!q.empty()){
			if(found){
				break;
			}
			auto i = q.front();//当前位置
			q.pop();
			int x = i.first;
			int y = i.second;

			
			for(int k = 0; k < 4; k ++){
				int nx = x + dx[k];
				int ny = y + dy[k];
				
				if(nx < 0 || nx >= h || ny < 0 || ny >= w){//越界 
					continue;
				}
				if(g[nx][ny] == '#'){//撞墙 
					continue;
				}
				if(dist[nx][ny] != -1){//访问过 
					continue;
				}
				if(g[nx][ny] == 'E'){//终点 
					cout<<dist[x][y] + 1<<endl;
					found = true;
					break;
				}
				
				dist[nx][ny] = dist[x][y] + 1;
				q.push({nx, ny});
			} 
		}
		if(found == false){//没找到 
			cout<<"-1"<<endl;
		}
		
		
		
		
		
	}  


 		
 		
}

机器人走迷宫

机器人走迷宫

查看题解查看答案

题目描述

Time Limit: 1000 ms

Memory Limit: 256 mb

有一个愚蠢的机器人走进一个w*h的迷宫,迷宫里有空地和陷阱。他想要访问迷宫的每个方格,但是它很笨,只会按照指令的方向走。当机器人不能走的时候,也就是下一步会遇到陷阱、迷宫边界或者访问过的格子,它会向右转90度(顺时针旋转90度,不能访问已经访问过的方格,且在原地只转一次,移动后可获得又一次旋转机会)。请问这个机器人最多可以经过多少个方格。

例如:

5 5

R....

.....

.....

.....

.....

机器人可以经过25个格子,但是

2 3

..L

...

机器人只能经过3个格子。

输入输出格式
输入描述:

对于每组数据,第一行两个数w和h,表示迷宫的行和列(1<=w,h<=10) 接下来w行每行有h个字符用于描述这个迷宫。迷宫的'.'表示空地,即为可以走的地方。'*'表示陷阱,即为不能走的地方。迷宫中有一个英文字母,表示机器人的出发点,字母只有'U','D','L','R'四种。分别表示机器人的初始指令是向上,向下,向左,向右。

输出描述:

对于每组数据,输出一个整数,即机器人一共经过多少个方格。

输入输出样例
输入样例#:

复制

复制代码
2 3
U..
.*.
4 4
R...
.**.
.**.
....
输出样例#:

复制

复制代码
4
12
题目来源
复制代码
中南大学/中山大学机试题
复制代码
#include<bits/stdc++.h>
using namespace std;

#define N 20

char g[N][N];//数组大小注意!!! 
int dist[N][N];//拿 int 的碗去接 char 的饭
int dx[4] = {-1, 0, 1, 0};//上右下左 
int dy[4] = {0, 1, 0, -1};

bool canPass(int nx, int ny, int w, int h){
	if(nx < 0 || nx >= w || ny < 0 || ny >= h){//边界 
		return false;
	}
	
	if(g[nx][ny] == '*'){//陷阱 
		return false; 
	}
	
	if(dist[nx][ny] != -1){//访问过 
		return false;
	}
	
	return true;
} 

int main(){
		int w, h;
		while(cin>>w>>h){
			int sx = -1, sy = -1, dir = -1;//初始信息 
			
			
			for(int i = 0; i < w; i ++){
				for(int j = 0; j < h; j ++){
						dist[i][j] = -1;//初始化为-1 
					
					
						cin>>g[i][j];
						if(g[i][j] == 'U'){//上 
							sx = i;
							sy = j;
							dir = 0;
						}
						if(g[i][j] == 'R'){//初始方向右 
							sx = i;
							sy = j;
							dir = 1;
						}
						if(g[i][j] == 'D'){//初始方向下 
							sx = i;
							sy = j;
							dir = 2;
						}
						if(g[i][j] == 'L'){//初始方向左 
							sx = i;
							sy = j;
							dir = 3;
						}
				}
			}//
			
			dist[sx][sy] = 1;//初始化 
			int count = 1;//起点以访问 
			
			while(true){//开始模拟 
				int nx = sx + dx[dir];
				int ny = sy + dy[dir];
				
				if(canPass(nx, ny, w, h)){//能走 
					dist[nx][ny] = 1;//更新
					sx = nx;
					sy = ny;
					count ++;
					continue; 
				} 
				
				int ndir = (dir + 1) % 4;//不能走就右转
				nx = sx + dx[ndir];
				ny = sy + dy[ndir];
				
				if(canPass(nx, ny, w, h)){//嫩个走了 
					dir = ndir;//记得更新方向 
					dist[nx][ny] = 1;//更新
					sx = nx;
					sy = ny;
					count ++;
					continue; 
				} 
				break;//还是走不了 
			}		
			cout<<count<<endl; 
	
		}
}
相关推荐
窝子面2 小时前
LeetCode练题一:async 和await 和 promise
开发语言·前端·javascript
踩着两条虫2 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(十六):扩展与定制之自定义组件与设计器面板
前端·agent·ai编程
爱敲代码的菜菜2 小时前
【项目】基于正倒排索引的Java文档搜索引擎
java·开发语言·前端·javascript·搜索引擎·servlet
李剑一2 小时前
告别冗余代码!Cesium点位图标模糊、重叠?自适应参数调优攻略,一次封装终身复用!
前端·vue.js·cesium
sz_denny2 小时前
chrome os 如何进入开发者模式
前端·chrome
踩着两条虫2 小时前
🔥 实测对比:VTJ.PRO凭啥让头部企业放弃自研低代码?
前端·vue.js·ai编程
han_2 小时前
JavaScript 检测网络连接状态,以及网络测速方案
前端·javascript
小李子呢02112 小时前
JavaScript 中 Map 的完整解析
前端·javascript·vue.js