U681125 [YCU Cup] 栗山未来的幻境突围

题目背景

“没有未来的未来,不是我想要的未来。” ![栗山未来](https://cdn.luogu.com.cn/upload/image_hosting/jhfx56cl.png) 异界士栗山未来握紧了手中的血之剑。为了拯救神原秋人,她独自闯入了一只极其强大的妖梦所构筑的幻境结界中。 这个幻境是一个庞大的迷宫,周围弥漫着致死的妖气。幻境的结构每时每刻都在重组,但秋人通过灵力共振,将幻境的核心种子传递给了未来。 “我不高兴。”未来推了推红色的眼镜,她必须用最快的速度穿过这片死亡迷宫,到达秋人所在的终点。

题目描述

幻境可以被抽象为一个 N × M 的二维网格。网格中的格子分为两种: * 0:表示安全的空地,未来可以安全通行。 * 1:表示凝结的妖气墙壁,绝对无法通行。 栗山未来目前身处起点坐标 (sx, sy),她需要前往秋人所在的终点坐标 (ex, ey)。她每次可以向上下左右四个方向移动一格,每移动一格消耗 1 个单位的时间。 **【幻境生成规则】** 为了还原这个复杂的结界,你必须使用题目提供的生成器类,实例化该类后,依次获取每一个格子的状态,自行在代码中完成地图的拼接。 生成器类内部维护了当前格子的坐标状态。每次调用获取下一个格子的方法时,它会严格按照**从第 1 行到第 N 行,每行从第 1 列到第 M 列**的顺序,返回对应格子的状态。 请在你的代码中原样加入以下幻境生成器类(请根据你使用的编程语言进行选择): **C++ 选手幻境生成器类:** ~~~cpp class MazeGenerator { private: unsigned int seed; int n, m, p, sx, sy, ex, ey; int current_i, current_j; unsigned int next_rand() { seed = seed * 1103515245 + 12345; return (seed / 65536) % 32768; } public: MazeGenerator(int _n, int _m, int _p, int _sx, int _sy, int _ex, int _ey, unsigned int _seed) { n = _n; m = _m; p = _p; sx = _sx; sy = _sy; ex = _ex; ey = _ey; seed = _seed; current_i = 1; current_j = 1; } int next_cell() { if (current_i > n) return -1; int is_wall = 0; if (current_i == sx && current_j == sy) { is_wall = 0; } else if (current_i == ex && current_j == ey) { is_wall = 0; } else { is_wall = (next_rand() % 100 < p) ? 1 : 0; } current_j++; if (current_j > m) { current_j = 1; current_i++; } return is_wall; } }; ~~~ **Java 选手幻境生成器类:** ~~~java class MazeGenerator { private long seed; private int n, m, p, sx, sy, ex, ey; private int current_i, current_j; private long next_rand() { seed = (seed * 1103515245L + 12345L) & 0xFFFFFFFFL; return (seed / 65536L) % 32768L; } public MazeGenerator(int n, int m, int p, int sx, int sy, int ex, int ey, long seed) { this.n = n; this.m = m; this.p = p; this.sx = sx; this.sy = sy; this.ex = ex; this.ey = ey; this.seed = seed; this.current_i = 1; this.current_j = 1; } public int next_cell() { if (current_i > n) return -1; int is_wall = 0; if (current_i == sx && current_j == sy) { is_wall = 0; } else if (current_i == ex && current_j == ey) { is_wall = 0; } else { is_wall = (next_rand() % 100 < p) ? 1 : 0; } current_j++; if (current_j > m) { current_j = 1; current_i++; } return is_wall; } } ~~~ 请你帮栗山未来算出:从起点走到终点,最少需要花费多少时间? 如果终点被妖气彻底封死,永远无法到达,请输出 -1。

输入格式

输入仅包含一行,包含 8 个整数,依次为: $N, M, P, sx, sy, ex, ey, Seed$ 分别表示:迷宫的行数、列数、墙壁生成阈值(百分比)、起点行号、起点列号、终点行号、终点列号,以及秋人传递的初始灵力种子。

输出格式

输出一行一个整数,表示最少花费的时间。如果不可达,输出 -1。

说明/提示

请先实例化类对象,再调用类对象的成员函数生成网格图。 **数据范围:** 对于 100% 的数据: * $1 ≤ N, M ≤ 3000$ * $0 ≤ P ≤ 100$ * $1 ≤ sx, ex ≤ N$ * $1 ≤ sy, ey ≤ M$ * $0 ≤ Seed ≤ 1000000000$