用友笔试 用友笔试题 0801
笔试时间:2024年08月01日 提前批
历史笔试传送门:2023秋招笔试合集
第一题
题目:小友的生产线
小友设计了一条新的生产线,在该条生产线上共有0-n种工序。每种工序之间可能存在上下游关系,如果一种工序没有下游工序,则为终点工序。如果一种工序其所有可能下游工序均可到达终点工序,则称该工序为合规工序。给你一个有向图,其中有n个节点,表示不同种工序,以及不同工序之间的关系,请计算该条生产线中,所有的合规工序,并按照升序排列。
注意:终点工序无下游工序,默认为合规工序。
输入描述
第一行输入正整数n,表示共有n个工序节点;
接下来n行,每行有j(1<=j<n)个数,表示工序节点i与其余j个工序节点上下游关系。
注意:若工序节点i为终点工序,则j=1,且数值为-1。
输出描述
输出一个数组,用来表示所有的合规工序,并按照升序排列。
补充说明:n == graph.length、1 <= n <= 104、0 <= n[i].length <= n、-1 <= n[i][j] <= n - 1、n[i] 按严格递增顺序排列,图中可能包含自环。
样例输入一
5
1 2 3 4
1 2
3 4
0 4
-1
样例输出一
4
说明:只有工序4是终点工序,即为合规工序
样例输入二
7
1 2
2 3
5
0
5
-1
-1
样例输出二
2 4 5 6
说明:工序5和6为终点工序,即为合规工序 工序2和4开始的所有下游工序最终都指向终点工序,按照升序排列最终结果为2,4,5,6。
参考题解
C++:[此代码未进行大量数据的测试,仅供参考]
Java:[此代码未进行大量数据的测试,仅供参考]
Python:[此代码未进行大量数据的测试,仅供参考]
第二题
题目:小友策划游戏人物
小友是一个游戏策划,他计划设计一个新人物,该人物的攻击模式较为特殊:他的附加攻击力可以拆分为n份(n>=2),这n份的乘积作为最终伤害值。游戏总监认为该人物过于超模(过于强大),要求对其附加攻击力增加上限限制。现在给你最终伤害值的上限和该人物的附加攻击力,请判断该人物的实际最终伤害值是否会超出给出的最终伤害值上限。
输入描述
输入两个数值,第一个数值为最终伤害值上限,第二个数值为该人物的附加攻击力。
例如:2920 22
2920为最终伤害值的上限
22为该人物的附加攻击力
输出描述
输入true或者false
true表示超出上限
false表示未超出上限
补充说明
最终伤害值上限不会超过int最大值
样例输入一
1 2
样例输出一
false
说明
最终伤害上限1
附加攻击力2
2=1+1
1*1=1
所以未超过上限
样例输入二
161 14
样例输出二
true
说明
14=3+3+3+3+2
3*3*3*3*2=162>161
所以超过上限
参考题解
动态规划
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <cmath> using namespace std; long long solve(long long n) { if (n <= 3) { return n - 1; } long long quotient = n / 3; long long remainder = n % 3; if (remainder == 0) { return pow(3, quotient); } else if (remainder == 1) { return pow(3, quotient - 1) * 4; } else { return pow(3, quotient) * 2; } } int main() { long long limit, power; cin >> limit >> power; long long ans = solve(power); if (ans > limit) { cout << "true" << endl; } else { cout << "false" << endl; } return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); long limit = scanner.nextLong(); long power = scanner.nextLong(); long ans = solve(power); if (ans > limit) { System.out.println("true"); } else{ System.out.println("false"); } } static long solve(long n) { if (n <= 3) { return n - 1; } long quotient = n / 3; long remainder = n % 3; if (remainder == 0) { return (long) Math.pow(3, quotient); } else if (remainder == 1) { return (long) Math.pow(3, quotient - 1) * 4; } else { return (long) Math.pow(3, quotient) * 2; } } }
Python:[此代码未进行大量数据的测试,仅供参考]
limit, power = map(int, input().split()) dp = [-1]*(power+1) def dfs(i): if i==2:return 1 if dp[i]!=-1:return dp[i] res = 0 for j in range(1,i//2+1): res = max(res, dfs(i-j)*j, j*(i-j)) dp[i] = res return res ans = dfs(power) if ans > limit: print("true") else: print("false")
第三题
题目:最佳工作任务安排
小友所在的部门在进行一系列复杂的开发项目。为了优化开发流程,部门要求工程师在不同的任务之间切换。每个任务有不同的执行时间,有些任务因为各种原因无法进行(标记为-1)。工程师可以在规定的跳跃范围内从一个任务跳到另一个任务,但每次执行任务需要消耗相应的时间。你的目标是找到一个从任务列表开头到结尾的执行顺序,使得总执行时间最小。如果存在多个总执行时间相同的顺序,返回按索引值更小优先的顺序。如果无法到达最后一个任务,返回一个空数组。
规则:
1.输入一个整数数组 tasks 表示任务执行时间,长度为 n。
2.输入一个整数 maxStep 表示单次切换任务的最大切换长度。
3.你从任务列表的第一个任务开始(tasks[0] 不是 -1)。
4.从任务 i 切换到任务 j,消耗的时间为 tasks[j]。
5.如果你当前位于任务 i,你只能跳到任务 i + k(满足 i + k <= n),其中 k 在范围 [1, maxStep] 内。
6.返回一个整数数组,包含你访问的任务索引顺序,使得总执行时间最小。如果存在多个总执行时间相同的顺序,返回索引值更小的顺序。
排序说明:
如果存在多个总执行时间相同的顺序:
假设方案 p1 = [Pa1, Pa2, ..., Pax] 和方案 p2 = [Pb1, Pb2, ..., Pbx]。
如果在两个方案中第一个不同的索引 j 处,Pa[j] 小于 Pb[j],则选择方案 p1。
如果所有索引都相同,但任务切换次数不同,则选择任务切换次数较少的一个方案。
提示:注意排序规则,如 1-2-3-4-5 和 1-4-5 , 假设两个方案所消耗的时间成本相同, 那么前面的方案更优。
输入描述
整数 N,代表任务 tasks 的长度
长度为 N 的数组 tasks 的各个元素
整数 M,代表每次切换任务的最大跳跃长度
输出描述
输出数组,代表总执行时间最短,并且索引值最小的执行方案。
补充说明:
1 <= tasks.length <= 1000
-1 <= tasks[i] <= 100
tasks[0] != -1
1 <= maxStep <= 100
样例输入一
5
1 2 4 -1 2
2
样例输出一
1 3 5
样例输入二
5
1 2 4 -1 2
1
样例输出二
[]
说明:
无法到达最后一个任务,输出字符串"[]"
参考题解
动态规划+路径回溯。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <vector> #include <climits> #include <algorithm> using namespace std; int main() { // 读取输入 int N, M; cin >> N; vector<int> task(N); for (int i = 0; i < N; ++i) { cin >> task[i]; } cin >> M; // 初始化 dp 数组 const int INF = INT_MAX; // 使用 INT_MAX 代替 inf vector<int> f(N, INF); f[0] = 0; vector<int> fm(N, -1); // 动态规划 for (int i = 1; i < N; ++i) { if (task[i] == -1) continue; for (int k = 1; k <= M; ++k) { if (i - k < 0) break; if (f[i - k] + task[i] < f[i] && task[i - k] != -1) { f[i] = f[i - k] + task[i]; fm[i] = i - k; } } } // 回溯找到路径 vector<int> res; int index = N - 1; while (true) { if (index == 0) { res.push_back(1); break; } res.push_back(index + 1); index = fm[index]; } // 反转并输出结果 reverse(res.begin(), res.end()); for (int r : res) { cout << r << " "; } return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 读取输入 int N = scanner.nextInt(); int[] task = new int[N]; for (int i = 0; i < N; i++) { task[i] = scanner.nextInt(); } int M = scanner.nextInt(); // 初始化 dp 数组 final int INF = Intege
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
持续收录字节、腾讯、阿里、美团、美团、拼多多、华为等笔试题解,包含python、C++、Java多种语言版本,持续更新中。