Uva1600 巡逻机器人

题目描述:

机器人从一个\(m\times n\)网格的左上角\((1,1)\)走到右下角\((m,n)\)。网格中的一些格子是空地,用\(0\)表示,其他格子是障碍,用\(1\)表示。机器人每次可以往四个方向走一格,但不能连续地穿越\(k\)个障碍,求最短路的长度。起点和中点保证是空地。

思路:

还是BFS求最短路,但是因为不能连续穿过\(k\)个障碍,所以与普通BFS不同的是这里需要考虑到达某个格子时已经连续走了几个障碍,而且即使格子已经被访问过,但如果新的访问耗费的障碍数能小于此前访问耗费的障碍数,也是可以访问的(与普通BFS的区别在这里)。后面这点是我开始没有想到,后面对着udebug上的测试数据调的时候才发现问题的,还有就是要考虑一下\(m=1,n=1\)的初始条件。

代码:

#include <iostream>
#include <queue>
#include <utility>
#include <algorithm>
#include <memory.h> 
using namespace std;
const int maxn = 20 + 2;
int b[maxn][maxn];
int d[maxn][maxn];
int obs[maxn][maxn];
int m, n, k;

const int dr[] = { 0, -1, 0, 1};
const int dc[] = { 1, 0, -1, 0};

pair<int, int> walk(pair<int, int> u, int i){
	pair<int, int> v;
	v.first = u.first + dr[i];
	v.second = u.second + dc[i];
	return v;
}

void solve(){
	queue<pair<int, int> > q;
	q.push(make_pair(1, 1));
	memset(d, -1, sizeof(d));
	memset(obs, 0, sizeof(obs));
	d[1][1] = 0;
	while(!q.empty()){
		pair<int, int> u = q.front(); q.pop();
		for(int i = 0; i < 4; ++i){
			pair<int, int> v = walk(u, i);
			if(v.first == m && v.second == n) { //抵达终点
				d[v.first][v.second] = d[u.first][u.second] + 1;
				printf("%d\n", d[v.first][v.second]); 
				return;
				}
			if(v.first > 0 && v.first <= m && v.second > 0 && v.second <= n && (d[v.first][v.second]<0||d[v.first][v.second]>0&&obs[u.first][u.second]+1<obs[v.first][v.second])){  //没有出界&&(没有被访问过||访问过但是当前路径到达这个点时耗费的障碍数更少)
				d[v.first][v.second] = d[u.first][u.second] + 1;//更新起点到达该网格的距离
				if(b[v.first][v.second] == 1){ //如果网格是一个障碍 
					obs[v.first][v.second] = obs[u.first][u.second] + 1;//获得当前网格连续经过的障碍数
					if(obs[v.first][v.second] > k) { d[v.first][v.second] = -1;  obs[v.first][v.second] = 0; continue;}//如果障碍数超过限制,将这个网格标记为没有访问,重新将其状态初始化。 
				}
				else obs[v.first][v.second] = 0; //不是网格就清零连续障碍数
				q.push(v);
			}
		}
	}
	if(d[m][n] < 0) printf("-1\n");//最终没能访问到终点,输出-1
	else printf("%d\n", d[m][n]); //这里是应对m=1,n=1的边界条件
}

int main(){
	//freopen("uva1600_in.txt", "r", stdin);
	//freopen("uva1600_out.txt", "w", stdout);
	int T; scanf("%d", &T);
	while(T--){
		scanf("%d%d%d", &m, &n, &k);
		for(int i = 1; i <= m; ++i){
			for(int j = 1; j <= n; ++j)
				scanf("%d", &b[i][j]);
		}
		solve();
	}
}
posted @ 2019-08-04 21:26  patrolli  阅读(250)  评论(0编辑  收藏  举报