2 solutions
-
1
这题的核心思想是把“跳跃 + 后退”转化成图上的最短路问题。 从第 i 个格子能跳到区间 [i+1, i+k[i]] 内的任意 j,然后落到 j−a[j] 上。 于是可以看成从 i 有边连向 (j−a[j])。每次跳跃的代价都是 1,所以整题就是求从 1 到 n 的最短路径,我们要用到BFS。 直接建图会超时,所以要用区间单调优化。 随着 BFS 按层推进,每个格子能跳到的右端总是单调不减的。我们用一个变量 maxs 记录当前已经扫描到的最右位置,每次只扩展还没访问过的新部分 [maxs+1, R],这样每个位置只会被处理一次,不会重复访问。 这个方法使压缩成线性扫描,整个 BFS 过程的时间复杂度降为 O(n)。
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; int n; int a[N], k[N], dist[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; for(int i = 1; i <= n; i++) cin >> a[i]; for(int i = 1; i <= n; i++) cin >> k[i]; for(int i = 1; i <= n; i++) a[i] = i - a[i]; fill(dist, dist + n + 1, INF); dist[1] = 0; queue<int> q; q.push(1); int maxs = 1; while(!q.empty()) { int u = q.front(); q.pop(); int r = min(n, u + k[u]); for(int j = max(maxs + 1, u + 1); j <= r; j++) { int v = a[j]; if(v >= 1 && dist[v] == INF) { dist[v] = dist[u] + 1; q.push(v); } } maxs = max(maxs, r); } if(dist[n] == INF) cout << -1 << "\n"; else cout << dist[n] << "\n"; return 0; }
Information
- ID
- 43
- Time
- 500ms
- Memory
- 512MiB
- Difficulty
- 3
- Tags
- # Submissions
- 201
- Accepted
- 32
- Uploaded By