zoukankan      html  css  js  c++  java
  • Uva1600 巡逻机器人

    题目描述:

    机器人从一个(m imes 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
    ", 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
    ");//最终没能访问到终点,输出-1
    	else printf("%d
    ", 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();
    	}
    }
    
  • 相关阅读:
    【Java多线程】Fork/Join 源码分析(三十一)
    【Java多线程】Fork/Join 框架(三十)
    【Java】 Iterator(迭代器)
    【Java多线程】ScheduledThreadPoolExecutor实现原理(二十九)
    【Java多线程】ScheduledThreadPoolExecutor详解(二十八)
    【Java多线程】Executor框架 (二十七)
    【Python基础编程252 ● 包 ● 使用import 包名 as 别名 语句导包】
    【Python基础编程251 ● 包 ● 使用from 包名 import * 语句导包】
    【Python基础编程250 ● 包 ● 导包的方式】
    【Python基础编程249 ● 包 ● 包的基本概念、作用和命名规则】
  • 原文地址:https://www.cnblogs.com/patrolli/p/11299838.html
Copyright © 2011-2022 走看看