1 条题解
-
0
自动搬运
来自洛谷,原作者为

Mars_Dingdang
最怕你一生碌碌无为,却总安慰自己平凡可贵搬运于
2025-08-24 22:32:09,当前版本为作者最后更新于2022-04-01 20:18:35,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
洛谷上这道题的第一篇题解。上海加油。
题目大意
Aladdin 已经厌倦了宫殿里的生活。他有一份稳定的工作,他的妻子 Jasmine 和孩子们都在路上,生活变得单调。在这一切的驱使下,他决定在安顿下来之前再进行一次冒险。他决定找到 Golden Pear,这是一件极为珍贵的传奇文物,至今无人能找到。
Aladdin 正在寻找的沙漠可以被看作是一个 的网格。行和列从上到下、从左到右编号为 到 。沙漠中的网格里一共有 个巫师,他们以一种不同寻常的方式帮助 Aladdin 完成任务。
Aladdin 星期一在沙漠的左上角 开始他的任务并面朝右。他的动作包括重复这些步骤:
- 如果当前的网格里有一个醒着的巫师,那么 Aladdin 会根据巫师说的话向左或向右转 度。
- 如果向前走会把 Aladdin 带出沙漠,他会转过 度。
- Aladdin 向前移动了一格,这将花费他一天的时间。
对于每个巫师,我们都知道他的位置和一周中每一天的活动计划。每个巫师的日程表是一个由七个字母(仅包含
L、R或S)组成的字符串,每个字符告诉我们巫师在一周中的某一天(从星期一开始)做什么。字母L表示 Aladdin 将在这一天被告知向左转,R表示 Aladdin 将在这一天被告知向右转,而S表示巫师那天正在睡觉。一个古老的预言说,在改变 次方向(通过步骤 和步骤 )后,Aladdin 会找到 Golden Pear。根据古老的预言,写一个程序来计算冒险将持续多少天。
大体思路
按照题意,定义一个状态为 ,表示当前位置 在星期 被访问,方向为 ,其中 ,,。因此,总的状态数为 。所以,我们完全可以用数组直接存储每一个状态。
记 表示上一次在星期 以 方向来到 时转向的次数,而 则表示上一次在星期 以 方向来到 时的天数。设当前转向次数为 ,天数为 ,那么,从上一次访问到这一次访问的循环,转向的次数为 ,循环的天数为 。
由于距离目标 次转向还有 次,可以完成的完整的循环次数为 $times=\left\lfloor\dfrac{K-k}{\Delta k}\right\rfloor$。那么,可以直接将转向次数增加 ,天数增加 。然后,在对 用目前状态的 进行更新即可。
具体实现时,还需要在永久循环的开头判断
L,R以及边界的转向,并调整 等。完整代码
#include <bits/stdc++.h> using namespace std; #define rep(ii,aa,bb) for(re int ii = aa; ii <= bb; ii++) #define Rep(ii,aa,bb) for(re int ii = aa; ii >= bb; ii--) typedef long long ll; typedef unsigned long long ull; typedef double db; typedef pair<int, int> PII; const int maxn = 205; namespace IO_ReadWrite { #define re register #define gg (p1 == p2 && (p2 = (p1 = _buf) + fread(_buf, 1, 1<<21, stdin), p1 == p2) ? EOF :*p1++) char _buf[1<<21], *p1 = _buf, *p2 = _buf; template <typename T> inline void read(T &x){ x = 0; re T f=1; re char c = gg; while(c > 57 || c < 48){if(c == '-') f = -1;c = gg;} while(c >= 48 &&c <= 57){x = (x<<1) + (x<<3) + (c^48);c = gg;} x *= f;return; } inline void ReadChar(char &c){ c = gg; while(!isalpha(c)) c = gg; } template <typename T> inline void write(T x){ if(x < 0) putchar('-'), x = -x; if(x > 9) write(x/10); putchar('0' + x % 10); } template <typename T> inline void writeln(T x){write(x); putchar('\n');} } using namespace IO_ReadWrite; int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};//right, down, left, up int N, M, K, turns[maxn][maxn][4][8]; char mp[maxn][maxn][8]; ll date[maxn][maxn][4][8]; int main () { scanf("%d%d%d", &N, &K, &M); rep(i, 1, M) { int x, y; scanf("%d%d", &x, &y); scanf("%s", mp[x][y]); } ll ans = 0; int x = 1, y = 1, dir = 0, day = 0, k = 0; while(1) { if(mp[x][y][day] == 'L') dir = (dir + 3) % 4, k ++; if(mp[x][y][day] == 'R') dir = (dir + 1) % 4, k ++; int nx = x + dx[dir], ny = y + dy[dir]; if(nx < 1 || nx > N || ny < 1 || ny > N) dir = (dir + 2) % 4, k ++; if(date[x][y][dir][day]) { int newK = k - turns[x][y][dir][day]; int left = K - k; ans += (left / newK) * (ans - date[x][y][dir][day]); k += (left / newK) * newK; } date[x][y][dir][day] = ans; turns[x][y][dir][day] = k; if(k >= K) break; x = x + dx[dir], y = y + dy[dir]; ans ++; if(++day >= 7) day = 0; } writeln(ans); return 0; }
- 1
信息
- ID
- 7020
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者