迷宫问题(最短路径)

http://ybt.ssoier.cn:8088/problem_show.php?pid=1255

【题目描述】

定义一个二维数组:

int maze[5][5] = {
0,1,0,0,0,
0,1,0,1,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,1,0,
};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

【输入】

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

【输出】

左上角到右下角的最短路径,格式如样例所示。

【输入样例】

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

【输出样例】

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

对于这类最短路径型题目,用宽搜的方式处理会比较方便,由于这道题,需要记录路径,可以用struct node{int x1;int y1} 类型的二维数组fp[][]记录,即fp[i][j]表示(i,j)来自(fp[i][j].x1,fp[i][j].y1),这一步是解决这道题的关键。

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

int maze[6][6];
bool flag[6][6];
struct node{
	int x1;
	int y1;
}; 
queue<node> qu;
node fp[6][6];//node类型的fp[i][j]用于记录(i,j)点的上一个点 
int a[]={1,-1,0,0};
int b[]={0,0,1,-1};
void print(int x,int y){
	if(x==0&&y==0) cout<<"("<<x<<", "<<y<<")"<<endl;
	else{
		print(fp[x][y].x1,fp[x][y].y1);
		//这两行是输出的关键,用递归的方式,按照从左上角开始的顺序,输出路径。 
		cout<<"("<<x<<", "<<y<<")"<<endl;//而且顺序不可以反 
	}
	return ;

}

void bfs(){
	node t;
	t.x1=0;
	t.y1=0;
	qu.push(t);
	while(!qu.empty()){
		node now=qu.front();
		qu.pop();
		if(now.x1==4&&now.y1==4){//当走到终点时 
			print(4,4);
			break;
		}
		for(int i=0;i<4;i++){
			int xx=now.x1+a[i];
			int yy=now.y1+b[i];
			if(xx<0||xx>=5||yy<0||yy>=5) continue;
			if(flag[xx][yy]){
				node temp;
				temp.x1=xx;
				temp.y1=yy;
				qu.push(temp);
				fp[xx][yy].x1=now.x1;
				fp[xx][yy].y1=now.y1;//这一步不能弄错
				flag[xx][yy]=false;
			}
		}
	}
	return ;
}

int main(){
	for(int i=0;i<5;i++){
		for(int j=0;j<5;j++){
			cin>>maze[i][j];
			if(maze[i][j]==0) flag[i][j]=true;
			
		}
	}
	bfs();
	return 0;
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于广度优先搜索(BFS)的 C 语言程序,可以解给定的 5x5 迷宫中左上角到右下角的最短路径。程序假设迷宫由 0 和 1 组成,其中 0 表示障碍,1 表示可通行的地方。 ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define ROWS 5 #define COLS 5 // 定义迷宫类型,包含行数、列数和二维数组表示的迷宫 typedef struct { int rows; int cols; int maze[ROWS][COLS]; } Maze; // 定义坐标类型,包含 x 和 y 坐标 typedef struct { int x; int y; } Coord; // 定义队列类型,用于广度优先搜索 typedef struct { Coord data[ROWS * COLS]; int front; int rear; } Queue; // 初始化队列 void initQueue(Queue *q) { q->front = 0; q->rear = -1; } // 插入元素到队列尾部 void enqueue(Queue *q, Coord c) { q->data[++q->rear] = c; } // 删除队列头部元素 Coord dequeue(Queue *q) { return q->data[q->front++]; } // 检查队列是否为空 bool isQueueEmpty(Queue *q) { return q->front > q->rear; } // 判断坐标是否在迷宫范围内 bool isCoordValid(Maze *maze, Coord c) { return c.x >= 0 && c.x < maze->cols && c.y >= 0 && c.y < maze->rows; } // 判断坐标是否为可通行的地方 bool isCoordPassable(Maze *maze, Coord c) { return maze->maze[c.y][c.x] == 1; } // 广度优先搜索,返回左上角到右下角的最短路径长度 int bfs(Maze *maze) { int dist[ROWS][COLS]; // 记录每个格子到起点的距离 Coord prev[ROWS][COLS]; // 记录每个格子的前驱格子 Queue q; Coord start = {0, 0}; // 起点坐标 Coord end = {maze->cols - 1, maze->rows - 1}; // 终点坐标 Coord dirs[4] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; // 四个方向 int i, j; // 初始化距离和前驱 for (i = 0; i < maze->rows; i++) { for (j = 0; j < maze->cols; j++) { dist[i][j] = -1; prev[i][j] = (Coord) {-1, -1}; } } // 从起点开始搜索 initQueue(&q); enqueue(&q, start); dist[start.y][start.x] = 0; // 广度优先搜索 while (!isQueueEmpty(&q)) { Coord curr = dequeue(&q); // 如果到达终点,则停止搜索 if (curr.x == end.x && curr.y == end.y) break; // 搜索四个方向 for (i = 0; i < 4; i++) { Coord next = {curr.x + dirs[i].x, curr.y + dirs[i].y}; // 如果下一个坐标在迷宫范围内且为可通行的地方,并且没有被访问过,则进行搜索 if (isCoordValid(maze, next) && isCoordPassable(maze, next) && dist[next.y][next.x] == -1) { dist[next.y][next.x] = dist[curr.y][curr.x] + 1; prev[next.y][next.x] = curr; enqueue(&q, next); } } } // 返回左上角到右下角的最短路径长度 return dist[end.y][end.x]; } int main() { int i, j; Maze maze; // 输入迷宫 printf("请输入迷宫(0 表示障碍,1 表示可通行的地方):\n"); for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { scanf("%d", &maze.maze[i][j]); } } maze.rows = ROWS; maze.cols = COLS; // 解迷宫左上角到右下角的最短路径长度 printf("迷宫左上角到右下角的最短路径长度为:%d\n", bfs(&maze)); return 0; } ``` 注意:该程序假设输入的迷宫是一个 5x5 的矩阵,若要处理其他规模的迷宫,需要相应修改常量 `ROWS` 和 `COLS` 的值,并输入相应规模的迷宫。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值