[图bfs] Patrol Robot 巡逻机器人 Uva1600

题目描述

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

题解

题目中表示,机器人可以越过 k 个障碍,那么一个值为1的网格就不一定是“障碍”。只有该网格是从前 k 个值为1的网格走过来时,才为真正的“障碍”。 该题可用bfs求最短路径,对值为0和值为1的网格作不同处理。值为0的网格只保存其距起点的距离,值为1的网格多保存一个表示该障碍为第几个障碍的信息。这样将0和1都看作可以入队的点,进行遍历,而第 k + 1 个值为1的点不入队。

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int maxn = 100;

const int dx[4] = {1,0,-1,0};
const int dy[4] = {0,1,0,-1};

struct point{
    int r, c;
    point(int r = 0, int c = 0):r(r), c(c){}
};
int k, m, n;
bool mp[21][21];
int dis[21][21];

bool bfs(){
    queue<point> qu;
    while(!qu.empty()) qu.pop();
    qu.push(point(0, 0));
    while(!qu.empty()){
        point s = qu.front();qu.pop();
        for(int i = 0; i<4; i++){
            int bx = s.r + dx[i], by = s.c + dy[i];
            if(!(0<=bx&&bx<m&&0<=by&&by<n)) continue;
            if(!mp[bx][by]){
                if(dis[bx][by]) continue;
                dis[bx][by] += ((dis[s.r][s.c]&0xffff) + 1);
            }
            else{
                int a = ((dis[s.r][s.c]&0xffff) + 1), b = (dis[s.r][s.c]>>16)+1;
                if(b>k || (dis[bx][by] <= (a|(b<<16)) && dis[bx][by])) continue;
                dis[bx][by] = a|(b<<16);
            }
            qu.push(point(bx, by));
            if(bx == m-1 && by == n-1) return true;
        }
    }
    return false;
}

int solve(){
    if(bfs()) return dis[m-1][n-1];
    else if(n == 1 && m == 1) return 0;
    else return -1;
}

int main(){
    int T;
    cin>>T;
    while(T--){
        memset(mp, 0, sizeof(mp));
        memset(dis, 0, sizeof(dis));
        cin>>m>>n>>k;
        for(int i = 0; i<m; ++i)
            for(int j = 0; j<n; ++j)
                cin>>mp[i][j];
        printf("%d\n", solve());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/loyxCCS/article/details/80032103