【笔试刷题】京东-2025.11.08-改编真题
✅ 秋招备战指南 ✅
💡 学习建议:
- 先尝试独立解题
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线180+套真题改编解析,后续会持续更新的
春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗
京东-2025.11.08
题目一:小兰的任务分配
1️⃣:使用动态规划,状态定义为完成任务数和使用外包券数
2️⃣:枚举每个任务的两种完成方式进行状态转移
3️⃣:从最多任务数开始查找满足精力值限制的最优方案
难度:中等
题目二:机械臂的路径规划
1️⃣:扩展BFS状态,增加下一步移动方向的维度
2️⃣:根据当前状态的方向限制进行状态转移
3️⃣:使用BFS求解最短路径问题
难度:中等
1. 小兰的任务分配
问题描述
小兰是一家项目管理公司的负责人,现在她手上有 个任务需要在今天完成。每个任务都可以通过两种方式完成:
-
自己亲自完成(需要消耗一定的精力值)
-
委托给专业团队完成(需要消耗较少的精力值,但需要使用一张外包券)
小兰当前拥有 点精力值和
张外包券。她希望在优先完成尽可能多任务的前提下,让自己的精力消耗最小化。
请你帮助小兰计算,她最多能完成多少个任务,以及在完成这么多任务的情况下,最少需要消耗多少精力值。
输入格式
第一行包含三个整数 ,分别表示任务数量、小兰拥有的精力值以及外包券数量。
接下来 行,每行两个整数
,表示第
个任务如果自己完成需要消耗
点精力值,如果委托完成需要消耗
点精力值。
输出格式
输出一行,包含两个整数,用空格分隔,分别表示小兰最多可以完成的任务数量,以及在完成这么多任务的情况下的最小精力消耗。
样例输入
3 20 1
8 5
7 4
10 6
4 25 2
10 6
8 5
12 7
9 6
样例输出
2 12
3 20
| 样例 | 解释说明 |
|---|---|
| 样例1 | 小兰有3个任务,20点精力值和1张外包券。最优策略是:完成第1个任务(委托,消耗5点精力),完成第2个任务(委托,但由于只有1张券,需要改为第2个任务自己完成消耗7点或第3个任务自己完成)。实际上,选择委托第2个任务(消耗4点精力和1张券)和自己完成第1个任务(消耗8点精力),共完成2个任务,消耗12点精力值。 |
| 样例2 | 小兰有4个任务,25点精力值和2张外包券。最优策略是完成3个任务,使用2张外包券和部分精力值,最终消耗20点精力值。 |
数据范围
题解
这道题的核心在于,我们需要在精力值和外包券的双重约束下,尽可能完成更多任务,并且在任务数量相同时选择精力消耗最小的方案。
解题思路
这是一个典型的背包类动态规划问题。我们定义状态 表示完成了
个任务且使用了
张外包券时,所需的最小精力值。
初始状态:,表示完成0个任务且不使用外包券时精力消耗为0,其余状态初始化为无穷大。
状态转移:对于每个任务,我们有两种选择:
- 自己完成:从状态
转移到
,精力值增加
- 委托完成:从状态
转移到
,精力值增加
为了避免重复计算,我们对每个任务按照倒序更新状态。
最后,我们从完成任务数最多的状态开始查找,找到第一个精力消耗不超过 且使用外包券不超过
的状态,这就是答案。
时间复杂度
状态数量为 ,每个任务的转移需要遍历所有状态,总体时间复杂度为
。在题目给定的数据范围内(
),这个复杂度是完全可以接受的。
空间复杂度
需要维护一个二维数组 ,空间复杂度为
。
参考代码
- Python
import sys
input = lambda: sys.stdin.readline().strip()
def solve():
# 读入任务数、精力值和外包券数量
N, X, Y = map(int, input().split())
tasks = []
for _ in range(N):
a, b = map(int, input().split())
tasks.append((a, b))
# dp[i][j] 表示完成i个任务使用j张外包券的最小精力消耗
INF = float('inf')
dp = [[INF] * (Y + 1) for _ in range(N + 1)]
dp[0][0] = 0
# 枚举每个任务
for idx in range(N):
self_cost, outsrc_cost = tasks[idx]
# 倒序遍历避免重复使用
for i in range(idx, -1, -1):
for j in range(Y + 1):
if dp[i][j] == INF:
continue
# 选择1:自己完成任务
dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + self_cost)
# 选择2:委托完成任务
if j + 1 <= Y:
dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j] + outsrc_cost)
# 找出最多完成的任务数和对应的最小精力消耗
ans_cnt, ans_energy = 0, 0
for i in range(N, -1, -1):
min_energy = min(dp[i])
if min_energy <= X:
ans_cnt = i
ans_energy = min_energy
break
print(ans_cnt, ans_energy)
if __name__ == "__main__":
solve()
- Cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
long long X;
int Y;
cin >> N >> X >> Y;
// 存储每个任务的两种完成方式的成本
vector<long long> self(N), outsrc(N);
for (int i = 0; i < N; ++i) {
cin >> self[i] >> outsrc[i];
}
// dp[i][j]: 完成i个任务使用j张券的最小精力值
const long long INF = 4e18;
vector<vector<long long>> dp(N + 1, vector<long long>(Y + 1, INF));
dp[0][0] = 0;
// 枚举每个任务
for (int k = 0; k < N; ++k) {
// 倒序更新状态
for (int i = k; i >= 0; --i) {
for (int j = 0; j <= Y; ++j) {
if (dp[i][j] >= INF) continue;
// 方式1:自己完成
if (dp[i + 1][j] > dp[i][j] + self[k]) {
dp[i + 1][j] = dp[i][j] + self[k];
}
// 方式2:委托完成
if (j + 1 <= Y && dp[i + 1][j + 1] > dp[i][j] + outsrc[k]) {
dp[i + 1][j + 1] = dp[i][j] + outsrc[k];
}
}
}
}
// 从最多任务数开始查找可行方案
int max_task = 0;
long long min_cost = 0;
for (int i = N; i >= 0; --i) {
long long cur_min = INF;
for (int j = 0; j <= Y; ++j) {
cur_min = min(cur_min, dp[i][j]);
}
if (cur_min <= X) {
max_task = i;
min_cost = cur_min;
break;
}
}
cout << max_task << ' ' << min_cost << '\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));
String[] firstLine = br.readLine().split(" ");
int taskNum = Integer.parseInt(firstLine[0]);
long totalEngy = Long.parseLong(firstLine[1]);
int ticketNum = Integer.parseInt(firstLine[2]);
// 读取每个任务的成本
long[] selfCost = new long[taskNum];
long[] outsrcCost = new long[taskNum];
for (int i = 0; i < taskNum; i++) {
String[] line = br.readLine().split(" ");
selfCost[i] = Long.parseLong(line[0]);
outsrcCost[i] = Long.parseLong(line[1]);
}
// dp[i][j]: 完成i个任务用j张券的最小精力
final long INF = (long) 4e18;
long[][] dp = new long[taskNum + 1][ticketNum + 1];
for (int i = 0; i <= taskNum; i++) {
Arrays.fill(dp[i], INF);
}
dp[0][0] = 0;
// 处理每个任务
for (int idx = 0; idx < taskNum; idx++) {
// 倒序更新
for (int i = idx; i >= 0; i--) {
for (int j = 0; j <= ticketNum; j++) {
if (dp[i][j] == INF) continue;
// 选项1:自己做
dp[i + 1][j] = Math.min(dp[i + 1][j],
dp[i][j] + selfCost[idx]);
// 选项2:外包
if (j + 1 <= ticketNum) {
dp[i + 1][j + 1] = Math.min(dp[i + 1][j + 1],
dp[i][j] + outsrcCost[idx]);
}
}
}
}
// 查找最优解
int bestCnt = 0
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力
