Gym - 101755H Safe Path题解

原题

在这里插入图片描述
https://codeforces.com/gym/101755/problem/H

题目大意

就是走迷宫,就是这么没新意,不同的是这次怪物也会动,而且还是瞬移的
S是起点,F是重点,M是怪物,. 就是普通地砖
从M开始d格都是危险区域,也就是不能走的地方
能从起点到终点输出要走的步数,不能则输出**-1**

题目分析

还是走迷宫,还是搜索,不过这次是求最短路径,所以就要用bfs了,第一个遇到的显然是答案
这条“没新意”的题的数据规模很奇葩,没错,2 ≤ n·m ≤ 200000,这是什么意思呢?大概就是说你的数组不能耿直的开到二维了,不然开个bool a[200000][200000]就等着MLE吧
卡了一天
解决方法就是开个一维数组,然后假装它是个二维数组,可以拿一个二重指针存每一行第一个数据的地址,而我就直接a[i][j] = *((a + i * n) + m)了
还有就是卡了一下时间,如果你在搜索怪物的时候把最后一步也入队了,就会在某个数据点TLE,我是在第44个点……
其它的小优化应该不是重点,只要上面那个剪枝做了应该就能过了。

代码

#include<cstdio>
#include<cstring>

int const dirx[4] = {0,1,0,-1};
int const diry[4] = {1,0,-1,0};//简化搜索
bool been[400010];//本质是二维数组
int fx[2000010],fy[2000010],dis[2000010],ft,fs;
int bx = -1,by = -1,ex = -1,ey = -1;
int n,m,d;
bool flag,f2 = false;
void place()
{
//    f2 = true;
    while (fs <= ft)
    {
        if ((fx[fs] == bx && fy[fs] == by) || (fx[fs] == ex && fy[fs] == ey))
        {
            flag = false;
            return;
        }
//        *((been + fx[fs] * m) + fy[fs]) = true;
        if (dis[fs] + 1 <= d)
            for (int i = 0;i < 4;i++)
            {
                int nx = fx[fs] + dirx[i];
                int ny = fy[fs] + diry[i];
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                if (*((been + nx * m) + ny)) continue;
                *((been + nx * m) + ny) = true;
                if (dis[fs] <= d)
                {
                    ft++;
                    fx[ft] = nx;fy[ft] = ny;dis[ft] = dis[fs] + 1;
                }
                
            }
        fs++;
    }
}
int walk()
{
    fs = 0;ft = 0;
    fx[ft] = bx;fy[ft] = by;dis[ft] = 0;
    while (fs <= ft)
    {
            for (int i = 0;i < 4;i++)
            {
                int nx = fx[fs] + dirx[i];
                int ny = fy[fs] + diry[i];
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                if (*((been + nx * m) + ny)) continue;
                if (nx == ex && ny == ey) return (dis[fs] + 1);
                ft++;
                fx[ft] = nx;fy[ft] = ny;dis[ft] = dis[fs] + 1;
                *((been + fx[ft] * m) + fy[ft]) = true;
            }
        fs++;
    }
    return -1;
}
int main()
{
    scanf("%d%d%d",&n,&m,&d);
    getchar();
    memset(been,0,sizeof(been));
    fs = 0;ft = -1;flag = true;
    for (int i = 0;i < n;i++)
    {
        for (int j = 0;j < m;j++)
            switch (getchar())
            {
            case '.':
                break;
            case 'M':
                ft++;fx[ft] = i;fy[ft] = j;dis[ft] = 0;
                *((been + i * m) + j) = true;
//                fs = 0;ft = -1;
                break;
            case 'S':
                bx = i;by = j;
                break;
            case 'F':
                ex = i;ey = j;
                break;
            default:
                break;
            }
        getchar();
    }
    if (d >= n && d >= m && ft > 0) flag = false;
    if (flag) place();
    if(*((been + bx * m) + by) || *((been + ex * m) + ey)) flag = false;
    memset(fx,0,sizeof(fx));
    memset(fy,0,sizeof(fy));
    memset(dis,0,sizeof(dis));
    if (flag) printf("%d",walk());else printf("-1");
    return 0;
}

反思

数学太差了啊……连数都不会计
i + 1 < d等价i <= d……鬼知道我当时是怎么想的

发布了13 篇原创文章 · 获赞 0 · 访问量 145

猜你喜欢

转载自blog.csdn.net/juseice/article/details/103954292