uva1600 Patrol Robot(不同的BFS最短路)

uva1600 原题链接:https://vjudge.net/problem/UVA-1600

解析:

        这题很明显用BFS最短路来做(当然也有其他方法)。但是这题的BFS略有不同,和普通BFS(以下普通BFS均为此意)最大的区别在于:普通BFS能走的路是通路,一个子节点只能属于一个父节点,而本题可以跨越障碍。也就是说,走已经走过的点也可能是最优解(普通BFS走已经走过的点必然不是最优解)。这就导致了一个子节点可能属于多个父节点(从树的角度来看)。

详细的讲:

        普通BFS的结点只有两种情况,通或者不通;因此必然存在一个树可以连通所有通路结点,因此可以求出最短路径。

        本题则不然,本题至少有三种状态:通,有障碍但是可以走(即在k范围内),不通;因此不能单纯的连成一个二叉树,而是要连成一个图,在图中找最短路(图与树的区别见离散数学)。

解题策略:

        就本题来讲,在普通的BFS的基础上,去掉 判别 是否访问过当前结点 的数组增加一个数组 用来存储当前结点还能跨过几个障碍(由于BFS的特性,到同一个结点的步数必然是相同的,但是它跨过的障碍数可能不同)。可以知道,当然是已经跨越的障碍越少越好(即还可以跨越障碍的机会(以下用k表示)越多越好,因为之后可能还有障碍,这样就可以跨过更多的障碍)。因此每到一个结点,判断当前走法所剩的k值,如果小于当前结点的值(即之前走法有更大的k),就舍弃。

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int m,n,k;
const int maxn = 25;
int Map[maxn][maxn];
int dr[] = {1,0,-1,0};
int dc[] = {0,1,0,-1};
int bushu[maxn][maxn];//用来存放当前结点最大的 剩余的 跨障机会,即k
struct Node{
	int step;
	int r,c,k;
	Node(int r,int c,int k,int step = 0):r(r),c(c),k(k),step(step){}
};
int main()
{
	int t;
	cin >> t;
	while(t--){
		memset(bushu,-1,sizeof(bushu));
		int min_step = 999;
		cin >> m >> n;
		cin >> k;
		for(int i = 0;i < m;i++)
			for(int j = 0;j < n;j++)	cin >> Map[i][j];
		queue<Node> q;
		q.push(Node(0,0,k));
		while(!q.empty()){
			Node a = q.front();
			q.pop();
			if(a.r == m-1 && a.c == n-1){
				min_step = a.step;
				break;
			}	
			for(int i = 0;i < 4;i++){
				int r = a.r + dr[i];
				int c = a.c + dc[i];
				int step = a.step;
				if(r < 0 || r >= m || c < 0 || c >= n)	continue;
				if(bushu[r][c] >= a.k)	continue;
				else bushu[r][c] = a.k;
				if(Map[r][c] == 0)
					q.push(Node(r,c,k,step+1));
				else if(a.k)	q.push(Node(r,c,a.k-1,step+1));
			}
		}
		if(min_step == 999)	cout << -1 << endl;
		else	cout << min_step << endl;
	}
	return 0;
} 
以上均为本人个人总结,不足之处请与我讨论,谢谢!

猜你喜欢

转载自blog.csdn.net/weixin_41162823/article/details/80888246