2018, XI Samara Regional Intercollegiate Programming Contest H题- Safe Path

传送门:Safe Path

题意:问你能否从起始点到达出发点。注意,在地图的一些地区有怪兽,只要怪兽能在d步内到达你现在的位置,你会被立刻杀死。。

分析:BFS裸题,注意,N*M是2e5大小,把地图进行压缩一下~

代码如下:

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

const int INF = 1e9;
const int maxn = 2e5+233;
queue<int>que;
int dis[maxn];
bool vis[maxn];
int n,m,d;
int S,F,tot;
char s[maxn];

inline bool check(int x){
   return x>=0 && x<n*m;
}

void bfs1(){
   int dir[] = {-1,1,-m,m};
   int now,tmp;
   while (!que.empty()) {
       now = que.front();
       que.pop();
       if (dis[now]>=d) continue;
       for (int i=0; i<4; i++) {
           tmp = dir[i]+now;
           if (!check(tmp)) continue;
           if (i<=1 && now/m != tmp/m) continue;
           if (dis[now]+1>=dis[tmp]) continue;
           dis[tmp] = dis[now]+1;
           vis[tmp] = 1;
           que.push(tmp);
       }
   }
}

int bfs2(){
    int dir[] = {-1,1,-m,m};
    while (!que.empty()) que.pop();
    dis[S] = 0;
    vis[S] = 1;
    que.push(S);

    int now,tmp;
    while (!que.empty()) {
        now = que.front();
        que.pop();
        if (now == F) return dis[now];
        for (int i=0; i<4; i++) {
            tmp = now + dir[i];
            if (!check(tmp)) continue;
            if (i<=1 && now/m != tmp/m) continue;
            if (vis[tmp]) continue;
            vis[tmp]  = 1;
            dis[tmp] = dis[now]+1;
            que.push(tmp);
        }
    }

    return -1;
}

int main(){
    scanf("%d%d%d",&n,&m,&d);
    memset(dis,0x7f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    while (!que.empty()) que.pop();
    tot = 0;
    for (int i=0; i<n; i++) {
        scanf("%s",s);
        for (int j=0; j<m; j++) {
            if (s[j]=='S') S = tot;
            else  if (s[j]=='F') F = tot;
            else  if (s[j]=='M') dis[tot] = 0, vis[tot] = 1,que.push(tot);
            tot++;
        }
    }

    bfs1();
    if (vis[S] || vis[F]) { printf("-1\n"); return 0; }
    printf("%d\n",bfs2());
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值