【春招笔试】2025年5月25日得物机考真题改编题
✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题(建议用时:90分钟/套)
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线90+套真题改编解析,后续会持续更新的
春秋招合集 -> 互联网必备刷题宝典🔗
题目一:智能配送路径规划
1️⃣:计算最少使用次数公式
2️⃣:使用贪心策略构造字典序最小的移动方案
3️⃣:每步选择
保证最优性
难度:中等
这道题目的关键在于理解贪心算法的应用,通过数学公式计算最少步数,然后使用巧妙的贪心策略构造字典序最小的方案。算法具有 的时间复杂度,其中
是最少使用次数。
题目二:魔法书页重排
1️⃣:模拟循环右移操作,对每个
处理其倍数位置
2️⃣:收集倍数位置并进行循环移动
3️⃣:时间复杂度为
,利用调和级数性质
难度:中等
这道题目需要理解循环移动的概念并正确模拟整个过程。关键是对于每个 ,找到所有倍数位置并进行循环右移操作。通过调和级数的性质,总时间复杂度为
。
题目三:机器人导航路径计数
1️⃣:使用动态规划计算网格路径数量
2️⃣:状态转移方程
3️⃣:处理障碍物位置,结果对
取模
难度:中等
这道题目是经典的网格路径计数问题,通过动态规划求解。核心思想是每个位置的路径数等于上方和左方路径数之和,需要特别处理障碍物位置。算法时间复杂度为 。
01. 智能配送路径规划
问题描述
小兰是一名快递配送员,她需要在城市中的高楼间进行配送任务。城市中有一栋高楼,共有 层,从下往上依次编号为
。小兰配备了一台智能升降设备,每次使用这台设备可以帮助她向上移动若干层。
具体来说,假设小兰当前位于第 层,选择使用设备向上移动
层的高度,那么小兰就会到达第
层。由于设备的技术限制,每次移动的层数
必须满足
。
将地面视为第 层,小兰初始位于地面上。她想知道,如果要在使用设备次数最少的前提下恰好到达第
层,应该如何安排每次使用设备时向上移动的层数?为了便于设备的程序化控制,需要输出字典序最小的移动方案。
输入格式
第一行包含一个正整数 (
),表示测试数据的组数。
接下来 行,每行包含两个正整数
(
),分别表示目标楼层和每次最多可移动的层数。
输出格式
对于每组测试数据,第一行输出最少需要使用设备的次数,第二行输出字典序最小的移动方案。
样例输入
1
10 5
样例输出
2
5 5
数据范围
样例1 | 需要到达第10层,每次最多移动5层。最少使用2次:第一次移动5层到第5层,第二次移动5层到第10层。字典序最小的方案是 [5, 5] |
题解
这道题本质上是一个贪心算法问题。我们需要找到使用设备次数最少的方案,并且在所有最优方案中选择字典序最小的。
首先分析问题:要到达第 层,每次最多移动
层,那么最少需要的次数就是
(向上取整)。
关键在于如何构造字典序最小的方案。贪心策略是:在保证能够到达目标的前提下,每一步都尽可能选择较小的移动距离。
具体算法:
- 计算最少使用次数
- 对于第
次移动(
从
开始),设当前剩余距离为
,剩余次数为
- 这一步的移动距离
这个公式的含义是:如果剩余的所有步骤都走最大距离 ,能否覆盖剩余距离?如果可以,那就走最小值
;如果不行,就走刚好能保证后续步骤都能走满的最小值。
时间复杂度为 ,其中
是最少使用次数,空间复杂度为
。
参考代码
- Python
import sys
input = lambda: sys.stdin.readline().strip()
t = int(input())
for _ in range(t):
n, m = map(int, input().split())
# 计算最少使用次数
k = (n + m - 1) // m
print(k)
rem = n # 剩余距离
res = [] # 结果序列
for i in range(k):
rem_k = k - 1 - i # 剩余步数
# 贪心选择当前步长,保证字典序最小
step = max(1, rem - rem_k * m)
res.append(step)
rem -= step
print(' '.join(map(str, res)))
- Cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
// 计算最少使用次数
int k = (n + m - 1) / m;
cout << k << "\n";
int rem = n; // 剩余距离
vector<int> res;
for (int i = 0; i < k; i++) {
int rem_k = k - 1 - i; // 剩余步数
// 贪心选择当前步长
int step = max(1, rem - rem_k * m);
res.push_back(step);
rem -= step;
}
for (int i = 0; i < k; i++) {
cout << res[i];
if (i < k - 1) cout << " ";
}
cout << "\n";
}
return 0;
}
- Java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(System.out);
int t = Integer.parseInt(br.readLine());
while (t-- > 0) {
String[] line = br.readLine().split(" ");
int n = Integer.parseInt(line[0]);
int m = Integer.parseInt(line[1]);
// 计算最少使用次数
int k = (n + m - 1) / m;
pw.println(k);
int rem = n; // 剩余距离
List<Integer> res = new ArrayList<>();
for (int i = 0; i < k; i++) {
int remK = k - 1 - i; // 剩余步数
// 贪心选择当前步长
int step = Math.max(1, rem - remK * m);
res.add(step);
rem -= step;
}
for (int i = 0; i < k; i++) {
pw.print(res.get(i));
if (i < k - 1) pw.print(" ");
}
pw.println();
}
pw.close();
br.close();
}
}
02. 魔法书页重排
问题描述
小毛是一位魔法师,他有一本古老的魔法书,书中有 页,每页都刻有一个魔法符号。最初,第
页上刻着数字
。
现在小毛需要按照古老的仪式来重新排列这些魔法符号。仪式的规则是:按照从小到大的顺序,对于每个 之间的整数
,将所有页码为
的倍数的页面上的魔法符号向右循环移动一位。
具体来说,如果有 个页面的页码是
的倍数,分别为
(按页码从小到大排列),那么这些页面上的魔法符号会按如下方式移动:
页的符号移动到
页,
页的符号移动到
页,以此类推。
请输出仪式完成后每页上的魔法符号是什么。
输入格式
第一行包含一个正整数 (
),表示魔法书的页数。
输出格式
第一行包含 个整数,第
个整数表示第
页上的魔法符号。
样例输入
5
8
样例输出
5 3 2 1 4
8 7 3 5 4 2 6 1
数据范围
样例1 | 初始状态:[1,2,3,4,5]。x=1时,所有页面循环右移:[5,1,2,3,4]。x=2时,页面2,4循环右移:[5,3,2,1,4]。x=3时,页面3循环右移:不变。x=4,5 |
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力