得物笔试 得物笔试题 0517
笔试时间:2025年5月17日
往年笔试合集:
第一题:迷幻森林
dd被困在了一个迷幻森林,现在她面前有一条凶险的大河,河中央有n个神奇的浮块,浮块按1~n顺序标号,但两两并不相接,第i个浮块上有一个数字a[i],可能是正数,也可能是负数,每块浮块都附带一个魔法结果用于传送,当a[i]为正数时,dd可以选择传送到第i+k(1≤k≤a[i])个浮块上,当dd抵达n号浮块时才可以顺利脱身,显然不管a[n]是多少,都没有任何意义,当a[i]为负时,dd只能选择标号小于等于i+a[i]的任意一块浮块进行传送,当i+a[i]<1时,默认只能传送到1的位置,每次传送都会花费1s的时间,随着时间的流逝,迷雾森林的空气会被逐渐榨干,她现在在1号浮块,她想知道,她最快多久能顺利脱身,如果始终无法逃脱,请输出-1。
输入描述
第一行一个数n(2≤n≤2000)
接下来一行n个数ai表示浮块上的数字
输出描述
输出一行,表示对应的答案。
样例输入
4
2 2 -1 2
样例输出
2
说明:
1跳到2,1s
2跳到4,1s
共2s
参考题解
每个节点i可以传送到其他节点,具体取决于a[i]的值: 如果a[i]为正,可以从i传送到i+1到i+a[i]的任意节点。 如果a[i]为负,可以从i传送到1到i+a[i]的任意节点(如果i+a[i] < 1,则只能传送到1)。 广度优先搜索(BFS):由于每次传送的代价相同(1秒),BFS适合用来寻找最短路径。我们从节点1开始,逐层探索可以到达的节点,直到到达节点n或无法继续前进。 队列和访问标记:使用队列来管理当前层的节点,并用一个数组记录到达每个节点的最短时间,避免重复处理。
C++:
// C++ 版本
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n+1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<int> visited(n+1, -1);
deque<int> q;
q.push_back(1);
visited[1] = 0;
bool found = false;
while (!q.empty()) {
int cur = q.front();
q.pop_front();
if (cur == n) {
found = true;
break;
}
int jump = a[cur];
if (jump > 0) {
// 向前跳
for (int nxt = cur + 1; nxt <= min(n, cur + jump); nxt++) {
if (visited[nxt] == -1) {
visited[nxt] = visited[cur] + 1;
q.push_back(nxt);
}
}
} else {
// 向后跳
for (int nxt = max(1, cur + jump); nxt < cur; nxt++) {
if (visited[nxt] == -1) {
visited[nxt] = visited[cur] + 1;
q.push_back(nxt);
}
}
}
}
cout << (found ? visited[n] : -1) << "\n";
return 0;
}
Java:
// Java 版本
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine().trim());
int[] a = new int[n+1];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 1; i <= n; i++) {
a[i] = Integer.parseInt(st.nextToken());
}
int[] visited = new int[n+1];
Arrays.fill(visited, -1);
Deque<Integer> queue = new ArrayDeque<>();
queue.addLast(1);
visited[1] = 0;
boolean found = false;
while (!queue.isEmpty()) {
int cur = queue.removeFirst();
if (cur == n) {
found = true;
break;
}
int jump = a[cur];
if (jump > 0) {
// 向前跳
for (int nxt = cur + 1; nxt <= Math.min(n, cur + jump); nxt++) {
if (visited[nxt] == -1) {
visited[nxt] = visited[cur] + 1;
queue.addLast(nxt);
}
}
} else {
// 向后跳
for (int nxt = Math.max(1, cur + jump); nxt < cur; nxt++) {
if (visited[nxt] == -1) {
visited[nxt] = visited[cur] + 1;
queue.addLast(nxt);
}
}
}
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

