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;
} 
以上均为本人个人总结,不足之处请与我讨论,谢谢!

转载于:https://www.cnblogs.com/long98/p/10352240.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值