Gym101755H(bfs)

题目

  • Problem Description
    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.

  • Input
    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.

  • Output
    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».

  • input

5 7 1
S.M...M
.......
.......
M...M..
......F
  • output
    12

题意

有一个n*m的地图,上面有怪物,起点,终点,每个怪物有行动距离d,在怪物d格范围之内都是危险的,无法通过
问起点到终点的最短路,如果不能到达则输出-1

思路

首先处理怪物,将危险范围全部标记在地图上,约等于围墙,然后就是走迷宫,找最短路,用bfs
因为地图太大无法用二维数组储存,只能用一维数组,需要处理坐标,存(x,y)转一维比较容易,我是存一维转(x,y)…

bfs

每次都从队列中拿出一个点p,查找p附近的点,如果有符合条件 且 未被访问过的点,则加入队列,值为p值+1,直到队列为空 或者 目标点 被访问,此时每个点上的值都是从起点去到该点的最短路

代码

#include <bits/stdc++.h>
using namespace std;
int m[200010];
int N,M,D;
int ans;
int fr,fc;
queue<int>q,moves;
int nr[4]= {-1,0,1,0};
int nc[4]= {0,-1,0,1};//上左下右

int transform(int r,int c)
{
    return c+(r-1)*M;
}

void bfs(int r,int c)
{
    moves.push(transform(r,c));
    m[transform(r,c)]=0;

    while(!moves.empty()) {
        r=moves.front()%M?moves.front()/M+1:moves.front()/M;
        c=moves.front()%M?moves.front()%M:M;
        moves.pop();
        for(int i=0; i<4; i++) {
            int dr=r+nr[i],dc=c+nc[i];
            if(dr>0&&dr<=N&&dc>0&&dc<=M) {
                if(m[transform(dr,dc)]==-1) {
                    m[transform(dr,dc)]=m[transform(r,c)]+1;
                    moves.push(transform(dr,dc));
                }
            }
        }
    }
}

void monster()
{
    int r,c;
    while(!q.empty()) {
        r=q.front()%M?q.front()/M+1:q.front()/M;
        c=q.front()%M?q.front()%M:M;
        q.pop();

        for(int i=0; i<4; i++) {
            int dr=r+nr[i],dc=c+nc[i];
            if(dr>0&&dr<=N&&dc>0&&dc<=M) {
                if( m[transform(dr,dc)] < m[transform(r,c)]-1 )  {
                    m[transform(dr,dc)]=m[transform(r,c)]-1;
                    q.push(transform(dr,dc));
                }
            }
        }
    }
}


int main()
{
    int sr,sc;
    while( scanf("%d %d %d",&N,&M,&D)!=EOF ) {
        getchar();
        for(int r=1; r<=N; ++r) {
            for(int c=1; c<=M; ++c) {
                scanf("%c",&m[transform(r,c)]);
                if(m[transform(r,c)]=='M') q.push(transform(r,c)),m[transform(r,c)]=D;
                else if(m[transform(r,c)]=='.')	m[transform(r,c)]=-1;
                else if(m[transform(r,c)]=='S') m[transform(r,c)]=-1,sr=r,sc=c;
                else if(m[transform(r,c)]=='F') m[transform(r,c)]=-1,fr=r,fc=c;
            }
            getchar();
        }
        monster();

        if(m[transform(sr,sc)] != -1 || m[transform(fr,fc)] != -1 ) {
            printf("-1\n");
            continue;
        }
  
        while(!moves.empty())
            moves.pop();
    
        bfs(sr,sc);

        if(m[transform(fr,fc)]==-1)
            printf("-1\n");
        else
            printf("%d\n",m[transform(fr,fc)]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值