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

分析 : 很明显的BFS最短路,但是这里有坑呀!如果只是单纯使用二维数组去标记是否已经访问过改点是错误的做法,走到该点的机器人因为有穿越障碍物的步数限制,所以可能有些 略绕但是行得通的路 就会被二维数组这种标记方式把路给封死,比如下面这个例子,假设BFS机器人的走位是先右后左,并且k = 3,如果采用二维标记则会出错

0 1 1 1 1

0 1 1 1 0

为什么会有这种情况呢?因为在普通BFS中能走的都是通路,如果当前点再去走已经被标记的点必然不是最优,而现在对于机器人而言,又有一个可跨越障碍的步数这个限制,那么走到某一个点当然是机器人还能跨越障碍物的步数越多越好,也就是说对于同一个点只要没有走已经走过的点必然不是最优这种条件的话,就要慎重考虑使用普通的BFS解法了!现在回到这个题,其实解决的办法就是给vis再增加一个维度,表示当前机器人是跨越了多少个障碍物来到这里的这个状态即可。不过实际上根据刚刚的分析,我们可以做个小小的优化,就是如果当前机器人到达这个点还能跨越障碍物的步数少于之前已经来过这里的机器人的话,那必然不是最优,无需入队!

#include<bits/stdc++.h>
using namespace std;
int n, m, k, ans;
struct robot
{
    robot(int r, int c, int C, int s):row(r), col(c), cross(C), step(s){};
    int row, col, cross, step;
};
, -, ,  };
,  , , -};
][][], G[][];
][];//记录当前机器人还剩的跨越障碍物的机会
 || c<); }
inline void BFS()
{
    queue<robot> q;
    memset(vis, false, sizeof(vis));
    memset(Chance, 0x3f, sizeof(Chance));
    q.push(robot(,,,));
    vis[][][] = true;
    while(!q.empty()){
        robot tmp = q.front();
        q.pop();
        if(tmp.row==n && tmp.col==m){
            ans = tmp.step;
            break;
        }
        ; i<; i++){
            int row = tmp.row + dr[i];
            int col = tmp.col + dc[i];
            int C = tmp.cross;
            ;
            ;
            if( !bound(row, col) && C <= k && !vis[row][col][C] && C < Chance[row][col]){//当前机器人到达这个点还能跨越更多的障碍物
                vis[row][col][C] = true;
                Chance[row][col] = C;
                q.push(robot(row, col, C, tmp.step+));
            }
        }
    }
}
int main(void)
{
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int nCase;
    scanf("%d", &nCase);
    while(nCase--){
        scanf("%d %d %d", &n, &m, &k);
        ans = -;
        memset(G, false, sizeof(G));
        ; i<=n; i++){
            ; j<=m; j++){
                int BOOL;
                scanf("%d", &BOOL);
                if(!BOOL) G[i][j] = true;
            }
        }
        BFS();
        printf("%d\n", ans);
    }
    ;
}

瞎 : 已经碰见过两次这种可以跨障碍物的BFS最短路题了,要时刻清楚vis标记的是状态,根据状态有无更优来舍取是否入队操作。

UVa 1600 Patrol Robot (BFS最短路 && 略不一样的vis标记)的更多相关文章

  1. Uva 1600 Patrol Robot (BFS 最短路)

    这道题运用的知识点是求最短路的算法.一种方法是利用BFS来求最短路. 需要注意的是,我们要用一个三维数组来表示此状态是否访问过,而不是三维数组.因为相同的坐标可以通过不同的穿墙方式到达. #inclu ...

  2. UVa 1600 Patrol Robot(BFS)

    题意: 给定一个n*m的图, 有一个机器人需要从左上角(1,1)到右下角(n,m), 网格中一些格子是空地, 一些格子是障碍, 机器人每次能走4个方向, 但不能连续穿越k(0<= k <= ...

  3. UVA 1600 Patrol Robot(机器人穿越障碍最短路线BFS)

    UVA 1600 Patrol Robot   Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu   ...

  4. UVa 1600 Patrol Robot【BFS】

    题意:给出一个n*m的矩阵,1代表墙,0代表空地,不能连续k次穿过墙,求从起点到达终点的最短路的长度 给vis数组再加一维状态,表示当前还剩下的能够穿越的墙的次数,每次碰到墙,当前的k减去1,碰到0, ...

  5. UVA - 1600 Patrol Robot (巡逻机器人)(bfs)

    题意:从(1,1)走到(m,n),最多能连续穿越k个障碍,求最短路. 分析:obstacle队列记录当前点所穿越的障碍数,如果小于k可继续穿越障碍,否则不能,bfs即可. #pragma commen ...

  6. UVa 1600 Patrol Robot (习题 6-5)

    传送门: https://uva.onlinejudge.org/external/16/1600.pdf 多状态广搜 网上题解: 给vis数组再加一维状态,表示当前还剩下的能够穿越的墙的次数,每次碰 ...

  7. UVa 1600 Patrol Robot(三维广搜)

    A robot has to patrol around a rectangular area which is in a form of m x n grid (m rows and ncolumn ...

  8. UVA 1600 Patrol Robot

    带状态的bfs 用一个数(ks)来表示状态-当前连续穿越的障碍数: step表示当前走过的步数: visit数组也加一个状态: #include <iostream> #include & ...

  9. 【UVa】1600 Patrol Robot(dfs)

    题目 题目     分析 bfs可以搞,但是我还是喜欢dfs,要记忆化不然会T     代码 #include <cstdio> #include <cstring> #inc ...

随机推荐

  1. 深入理解java:2.3.4. 并发编程concurrent包 之容器ConcurrentLinkedQueue(非阻塞的并发队列---循环CAS)

    1.    引言 在并发编程中我们有时候需要使用线程安全的队列. 如果我们要实现一个线程安全的队列有两种实现方式:一种是使用阻塞算法,另一种是使用非阻塞算法. 使用阻塞算法的队列可以用一个锁(入队和出 ...

  2. 利用三层交换机实现VLAN间路由

    利用三层交换机实现VLAN间路由 本实验模拟企业网络场景.公司有两个部门一销 售部和客服部,分别规划使用VLAN 10和VLAN 20.其中销售部下有两台终端PC-1和PC-2,客服部下有一台终端PC ...

  3. 国产银河麒麟 安装wps 的简单方法

    前提说明 银河麒麟 是总部在天津的企业 有国防科大还有 ubuntu的母公司一起在维护 主要的产品有 优麒麟 还有 银河麒麟 优麒麟 可以看做是 国产版的ubuntu的社区版 银河麒麟 则是 面向国内 ...

  4. spring aop之父子容器

    需求;项目对外提供接口,要求每个对外接口都要进行token认证. 解决办法:写一个token认证的工具类,在每个需要认证的接口方法开始的地方,调用工具类中的token认证方法. 问题:因为要满足指定条 ...

  5. qDebug的用法

    qDebug用于在控制台输出调试信息,主要有以下几种用法. 1.类似c++的cout函数 QString str="world"; qDebug()<<"he ...

  6. 洛谷 P3258 松鼠的新家 题解

    题面 貌似这道题暴力加玄学优化就可以AC? 下面是正解: 1.树链剖分: 我们在u到v之间都放一个糖果,可以将松鼠它家u到v的糖果数都加1.每一次将a[i]到a[i+1] (a数组是访问顺序)的节点加 ...

  7. 抖音很火的存钱计划,让python告诉你总共可以存到多少钱!

    抖音上有个很火的存钱计划,说是第一天存1块钱,第二天存2块钱,第三天存3块钱.....依此类推存365天,总共可以存到多少钱,我们现在用python告诉你怎么做: #定个初始存入金额 money = ...

  8. 编号001:deque用法暂时总结

    #deque的用法总结 In [1]: """ 所在地址:from collections import deque 现在知道的情况总结: 1.deque的用法与list ...

  9. mysql导入导出数据,备份,恢复数据

    MYSQL 实现导入数据 .备份和恢复数据库 1.使用msql命令导入数据 # mysql -uroot -p 需要选择一个数据库 < runoob.sql #mysql -u username ...

  10. 一个常用的通过curl发送HTTP请求的函数

    function: function curl_get($url, $params) { return curl_http($url, $params, 'GET'); } function curl ...