洛谷P6207 题解

题目传送门

这道题很显然是一道搜索题,这里讲讲宽搜的做法。

读题,这道题要求我们输出到终点的路径,所以我们不仅要考虑宽搜的过程,还要记录下经过的路径。

首先宽搜的模板可以先写出来,然后就是记录路径的问题了,怎么实现它呢?

记录路径,其实就是记录每个点是由哪个点走来的,这里我构思了一种链式结构,在搜到终点后找到它的上一个点,再找到它的上上个点,再找到它的上上上个点……直到找到起点,然后利用递归来将它们反向输出。

如图所示:

4 5
.*...
...**
**...
**.*.

AC代码:

#include <iostream>
#include <queue>

using namespace std;
const int N = 120, M = 100010;
struct node{
	int now, x, y; //now存的是此点的坐标在point数组中的下标
}a, t;
struct path{
	int las, px, py;
}point[M];
int n, m;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}; //下, 右, 上, 左 
char mapp[N][N];
int tt; //point数组的下标 
bool vis[N][N];
queue <node> q;

void print(int x) { //递归, 先输出前面的点, 再输出现在的点 
	if(x == -1) return ;
	print(point[x].las); 
	printf("%d %d\n", point[x].px, point[x].py);
}

void bfs() {
	a.x = 1, a.y = 1;
	a.now = ++tt;
	point[tt].px = a.x, point[tt].py = a.y;
	point[tt].las = -1; //第一个点的前一个点的下标指向-1 
	vis[a.x][a.y] = true;
	q.push(a);
	
	while(!q.empty()) {
		t = q.front();
		q.pop();
		if(t.x == n && t.y == m) {
			print(t.now);
			return ;
		}
		for(int i = 0; i < 4; i++) {
			a.x = t.x + dx[i], a.y = t.y + dy[i];
			if(a.x < 1 || a.x > n || a.y < 1 || a.y > m ) continue;
			if(vis[a.x][a.y]) continue;
			
			a.now = ++tt;
			point[tt].px = a.x, point[tt].py = a.y;
			point[tt].las = t.now; //此点是由t走来的,因此它的las指针应该指向t在数组中的位置 
			vis[a.x][a.y] = true;
			q.push(a);
		} 
	}
}

int main() {
	//             x   y
	scanf("%d%d", &n, &m);
	
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> mapp[i][j];
			if(mapp[i][j] == '*') vis[i][j] = true;
		}
	}
	
	bfs();
	
	for(int i = 1; i <= tt; i++) {
		cout << point[i].px << " " << point[i].py << " " << point[i].las << endl; 
	}
	
	return 0;
}

完结撒花!!!

posted @ 2023-09-26 15:40  Brilliant11001  阅读(17)  评论(0编辑  收藏  举报