Gym - 101755H Safe Path 题解*

题面:

You play a new RPG. The world map in it is represented by a grid of n × m cells. Any playing character staying in some cell can move from this cell in four directions — to the cells to the left, right, forward and back, but not leaving the world map.
Monsters live in some cells. If at some moment of time you are in the cell which is reachable by some monster in d steps or less, he immediately runs to you and kills you.
You have to get alive from one cell of game field to another. Determine whether it is possible and if yes, find the minimal number of steps required to do it.

输入:

The first line contains three non-negative integers n, m and d (2 ≤ n·m ≤ 200000, 0 ≤ d ≤ 200000) — the size of the map and the maximal distance at which monsters are dangerous.
Each of the next n lines contains m characters. These characters can be equal to «.», «M», «S» and «F», which denote empty cell, cell with monster, start cell and finish cell, correspondingly. Start and finish cells are empty and are presented in the input exactly once.

输出:

If it is possible to get alive from start cell to finish cell, output minimal number of steps required to do it. Otherwise, output «-1».

题目翻译:

你现在在玩♂一个RPG游戏,游戏地图上面有n*m个点.玩家的角色要从给定的起点走到终点(每一步可以选择向上下左右四个方向走).
地图上面有一些♂恶魔,如果你和他们的距离不超过d步,他就会抓住你(一步是指往上下左右其中一个方向走一步).

输入:

第一行是三个整数n,m,d
n,m代表地图的大小.d代表恶魔的移动步数.

输出

如果角色能够到达终点,那么输出到达终点所需的步数,否则输出-1.

题目分析:

这是一道非常明显的bfs题.
我们先读入地图,记录下所有恶魔的位置,开始的位置,结束的位置.
恶魔所在的点标记为’M’,没有恶魔的点标记为’.’.
读入完之后先用bfs把恶魔能够到达的点都标记成’X’.
这里注意,如果有一个点原本是’M’,那么不要把他赋值成’X’,不然就会有恶魔被其他恶魔覆盖.

把起点放入队列.
然后从队列中取出一个点,把当前能够到达的点都放到队列中,并且把能够入队的点都赋值成’X’.
直到队列为空或者已经到达终点.
如果到达终点就输出步数.
队列为空就输出"-1"

特别要注意:
每次把一个点放入队列之后,要马上把他赋值成’X’,否则在判断其他点的时候,这个点会被多次放入队列,导致爆内存.

代码:

#include<stdio.h>
#include<queue>

using namespace std;

struct cell{
    int i, step;
}s, f, c;
queue<cell> q;

int n, m, d;
char ditu[200000];
int directx[4] = {0,0,1,-1}, directy[4] = {1,-1,0,0};

int main(){
    scanf("%d%d%d", &n, &m, &d);
    for(int i = 0; i < n*m; ++i){
        scanf(" %c", ditu+i);
        if(ditu[i] == 'S')
            s.i = i, s.step = 0;
        if(ditu[i] == 'F')
            f.i = i, f.step = -1;
        if(ditu[i] == 'M'){
            c.i = i;
            c.step = 0;
            q.push(c);
        }

    }

    while(!q.empty()){
        c = q.front();
        q.pop();
            if(c.step < d){
                int x = c.i / m;
                int y = c.i % m;
                for(int i = 0; i < 4 ;++i)
                    if(x + directx[i] >= 0 && x + directx[i] < n && y + directy[i] >= 0 && y + directy[i] < m){
                        cell ic;
                        ic.i = (x + directx[i])*m + y + directy[i];
                        ic.step = c.step+1;
                        if(ditu[ic.i] != 'M' && ditu[ic.i] != 'X'){
                            q.push(ic);
                            ditu[ic.i] = 'X';
                        }
                    }
            }

    }

    if(ditu[s.i] == 'X' || ditu[f.i] == 'X'){
        printf("-1\n");
        return 0;
    }

    ditu[s.i] = 'X';

    q.push(s);
    while(!q.empty()){
        c = q.front();
        q.pop();
        if(c.i == f.i){
            printf("%d\n", c.step);
            return 0;
        }
        int x = c.i / m;
        int y = c.i % m;
            for(int i = 0; i < 4 ;++i)
                if(x + directx[i] >= 0 && x + directx[i] < n && y + directy[i] >= 0 && y + directy[i] < m){
                    cell ic;
                    ic.i = (x + directx[i])*m + y + directy[i];
                    ic.step = c.step+1;
                    if(ditu[ic.i] != 'X' && ditu[ic.i] != 'M'){
                        q.push(ic);
                        ditu[ic.i] = 'X';//入队之后一定要马上把这个点赋值成'X'!!!!
                    }
                }
    }

    printf("-1\n");
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值